| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-vue-plus</artifactId> |
| | | <version>5.5.3</version> |
| | | <packaging>pom</packaging> |
| | | <name>RuoYi-Vue-Plus</name> |
| | | <description>Dromara RuoYi-Vue-Pluså¤ç§æ·ç®¡çç³»ç»</description> |
| | | <url>https://gitee.com/dromara/RuoYi-Vue-Plus</url> |
| | | <modules> |
| | | <module>ruoyi-admin</module> |
| | | <module>ruoyi-common</module> |
| | | <module>ruoyi-extend</module> |
| | | <module>ruoyi-modules</module> |
| | | </modules> |
| | | <properties> |
| | | <spring-boot-admin.version>3.5.6</spring-boot-admin.version> |
| | | <dynamic-ds.version>4.3.1</dynamic-ds.version> |
| | | <aws.sdk.version>2.28.22</aws.sdk.version> |
| | | <hutool.version>5.8.43</hutool.version> |
| | | <spring-boot.version>3.5.10</spring-boot.version> |
| | | <p6spy.version>3.9.1</p6spy.version> |
| | | <flatten-maven-plugin.version>1.3.0</flatten-maven-plugin.version> |
| | | <snailjob.version>1.9.0</snailjob.version> |
| | | <springdoc.version>2.8.15</springdoc.version> |
| | | <mapstruct-plus.version>1.5.0</mapstruct-plus.version> |
| | | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
| | | <fastjson.version>1.2.83</fastjson.version> |
| | | <skipTests>true</skipTests> |
| | | <anyline.version>8.7.3-20251210</anyline.version> |
| | | <therapi-javadoc.version>0.15.0</therapi-javadoc.version> |
| | | <lock4j.version>2.2.7</lock4j.version> |
| | | <warm-flow.version>1.8.4</warm-flow.version> |
| | | <sms4j.version>3.3.5</sms4j.version> |
| | | <mybatis.version>3.5.19</mybatis.version> |
| | | <maven-jar-plugin.version>3.4.2</maven-jar-plugin.version> |
| | | <java.version>17</java.version> |
| | | <bouncycastle.version>1.80</bouncycastle.version> |
| | | <maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version> |
| | | <fastexcel.version>1.3.0</fastexcel.version> |
| | | <mybatis-plus.version>3.5.16</mybatis-plus.version> |
| | | <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> |
| | | <revision>5.5.3</revision> |
| | | <lombok.version>1.18.42</lombok.version> |
| | | <maven-surefire-plugin.version>3.5.3</maven-surefire-plugin.version> |
| | | <mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version> |
| | | <ip2region.version>3.3.2</ip2region.version> |
| | | <satoken.version>1.44.0</satoken.version> |
| | | <redisson.version>3.52.0</redisson.version> |
| | | <justauth.version>1.16.7</justauth.version> |
| | | <maven-war-plugin.version>3.4.0</maven-war-plugin.version> |
| | | <velocity.version>2.3</velocity.version> |
| | | </properties> |
| | | <dependencyManagement> |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-dependencies</artifactId> |
| | | <version>${spring-boot.version}</version> |
| | | <type>pom</type> |
| | | <scope>import</scope> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>cn.hutool</groupId> |
| | | <artifactId>hutool-bom</artifactId> |
| | | <version>${hutool.version}</version> |
| | | <type>pom</type> |
| | | <scope>import</scope> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-bom</artifactId> |
| | | <version>5.5.3</version> |
| | | <type>pom</type> |
| | | <scope>import</scope> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springdoc</groupId> |
| | | <artifactId>springdoc-openapi-starter-webmvc-api</artifactId> |
| | | <version>${springdoc.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.github.therapi</groupId> |
| | | <artifactId>therapi-runtime-javadoc</artifactId> |
| | | <version>${therapi-javadoc.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.projectlombok</groupId> |
| | | <artifactId>lombok</artifactId> |
| | | <version>${lombok.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>cn.idev.excel</groupId> |
| | | <artifactId>fastexcel</artifactId> |
| | | <version>${fastexcel.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.apache.velocity</groupId> |
| | | <artifactId>velocity-engine-core</artifactId> |
| | | <version>${velocity.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>cn.dev33</groupId> |
| | | <artifactId>sa-token-spring-boot3-starter</artifactId> |
| | | <version>${satoken.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>cn.dev33</groupId> |
| | | <artifactId>sa-token-jwt</artifactId> |
| | | <version>${satoken.version}</version> |
| | | <exclusions> |
| | | <exclusion> |
| | | <groupId>cn.hutool</groupId> |
| | | <artifactId>hutool-all</artifactId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>cn.dev33</groupId> |
| | | <artifactId>sa-token-core</artifactId> |
| | | <version>${satoken.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>dynamic-datasource-spring-boot3-starter</artifactId> |
| | | <version>${dynamic-ds.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.mybatis</groupId> |
| | | <artifactId>mybatis</artifactId> |
| | | <version>${mybatis.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>mybatis-plus-spring-boot3-starter</artifactId> |
| | | <version>${mybatis-plus.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>mybatis-plus-jsqlparser</artifactId> |
| | | <version>${mybatis-plus.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>mybatis-plus-annotation</artifactId> |
| | | <version>${mybatis-plus.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>p6spy</groupId> |
| | | <artifactId>p6spy</artifactId> |
| | | <version>${p6spy.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>software.amazon.awssdk</groupId> |
| | | <artifactId>s3</artifactId> |
| | | <version>${aws.sdk.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>software.amazon.awssdk</groupId> |
| | | <artifactId>s3-transfer-manager</artifactId> |
| | | <version>${aws.sdk.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>software.amazon.awssdk</groupId> |
| | | <artifactId>netty-nio-client</artifactId> |
| | | <version>${aws.sdk.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara.sms4j</groupId> |
| | | <artifactId>sms4j-spring-boot-starter</artifactId> |
| | | <version>${sms4j.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>de.codecentric</groupId> |
| | | <artifactId>spring-boot-admin-starter-server</artifactId> |
| | | <version>${spring-boot-admin.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>de.codecentric</groupId> |
| | | <artifactId>spring-boot-admin-starter-client</artifactId> |
| | | <version>${spring-boot-admin.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.redisson</groupId> |
| | | <artifactId>redisson-spring-boot-starter</artifactId> |
| | | <version>${redisson.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>lock4j-redisson-spring-boot-starter</artifactId> |
| | | <version>${lock4j.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.aizuda</groupId> |
| | | <artifactId>snail-job-client-starter</artifactId> |
| | | <version>${snailjob.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.aizuda</groupId> |
| | | <artifactId>snail-job-client-job-core</artifactId> |
| | | <version>${snailjob.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.bouncycastle</groupId> |
| | | <artifactId>bcprov-jdk15to18</artifactId> |
| | | <version>${bouncycastle.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>io.github.linpeilie</groupId> |
| | | <artifactId>mapstruct-plus-spring-boot-starter</artifactId> |
| | | <version>${mapstruct-plus.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara.warm</groupId> |
| | | <artifactId>warm-flow-mybatis-plus-sb3-starter</artifactId> |
| | | <version>${warm-flow.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara.warm</groupId> |
| | | <artifactId>warm-flow-plugin-ui-sb-web</artifactId> |
| | | <version>${warm-flow.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>me.zhyd.oauth</groupId> |
| | | <artifactId>JustAuth</artifactId> |
| | | <version>${justauth.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.lionsoul</groupId> |
| | | <artifactId>ip2region</artifactId> |
| | | <version>${ip2region.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.alibaba</groupId> |
| | | <artifactId>fastjson</artifactId> |
| | | <version>${fastjson.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-system</artifactId> |
| | | <version>5.5.3</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-job</artifactId> |
| | | <version>5.5.3</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-generator</artifactId> |
| | | <version>5.5.3</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-demo</artifactId> |
| | | <version>5.5.3</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-qa</artifactId> |
| | | <version>5.5.3</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-workflow</artifactId> |
| | | <version>5.5.3</version> |
| | | </dependency> |
| | | </dependencies> |
| | | </dependencyManagement> |
| | | <repositories> |
| | | <repository> |
| | | <releases> |
| | | <enabled>true</enabled> |
| | | </releases> |
| | | <id>public</id> |
| | | <name>huawei nexus</name> |
| | | <url>https://mirrors.huaweicloud.com/repository/maven/</url> |
| | | </repository> |
| | | </repositories> |
| | | <pluginRepositories> |
| | | <pluginRepository> |
| | | <releases> |
| | | <enabled>true</enabled> |
| | | </releases> |
| | | <snapshots> |
| | | <enabled>false</enabled> |
| | | </snapshots> |
| | | <id>public</id> |
| | | <name>huawei nexus</name> |
| | | <url>https://mirrors.huaweicloud.com/repository/maven/</url> |
| | | </pluginRepository> |
| | | </pluginRepositories> |
| | | <build> |
| | | <resources> |
| | | <resource> |
| | | <filtering>false</filtering> |
| | | <directory>src/main/resources</directory> |
| | | </resource> |
| | | <resource> |
| | | <filtering>true</filtering> |
| | | <directory>src/main/resources</directory> |
| | | <includes> |
| | | <include>application*</include> |
| | | <include>bootstrap*</include> |
| | | <include>banner*</include> |
| | | </includes> |
| | | </resource> |
| | | </resources> |
| | | <plugins> |
| | | <plugin> |
| | | <artifactId>maven-compiler-plugin</artifactId> |
| | | <version>${maven-compiler-plugin.version}</version> |
| | | <configuration> |
| | | <source>${java.version}</source> |
| | | <target>${java.version}</target> |
| | | <encoding>${project.build.sourceEncoding}</encoding> |
| | | <annotationProcessorPaths> |
| | | <path> |
| | | <groupId>com.github.therapi</groupId> |
| | | <artifactId>therapi-runtime-javadoc-scribe</artifactId> |
| | | <version>${therapi-javadoc.version}</version> |
| | | </path> |
| | | <path> |
| | | <groupId>org.projectlombok</groupId> |
| | | <artifactId>lombok</artifactId> |
| | | <version>${lombok.version}</version> |
| | | </path> |
| | | <path> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-configuration-processor</artifactId> |
| | | <version>${spring-boot.version}</version> |
| | | </path> |
| | | <path> |
| | | <groupId>io.github.linpeilie</groupId> |
| | | <artifactId>mapstruct-plus-processor</artifactId> |
| | | <version>${mapstruct-plus.version}</version> |
| | | </path> |
| | | <path> |
| | | <groupId>org.projectlombok</groupId> |
| | | <artifactId>lombok-mapstruct-binding</artifactId> |
| | | <version>${mapstruct-plus.lombok.version}</version> |
| | | </path> |
| | | </annotationProcessorPaths> |
| | | <compilerArgs> |
| | | <arg>-parameters</arg> |
| | | </compilerArgs> |
| | | </configuration> |
| | | </plugin> |
| | | <plugin> |
| | | <artifactId>maven-surefire-plugin</artifactId> |
| | | <version>${maven-surefire-plugin.version}</version> |
| | | <configuration> |
| | | <argLine>-Dfile.encoding=UTF-8</argLine> |
| | | <groups>${profiles.active}</groups> |
| | | <excludedGroups>exclude</excludedGroups> |
| | | </configuration> |
| | | </plugin> |
| | | <plugin> |
| | | <groupId>org.codehaus.mojo</groupId> |
| | | <artifactId>flatten-maven-plugin</artifactId> |
| | | <version>${flatten-maven-plugin.version}</version> |
| | | <executions> |
| | | <execution> |
| | | <id>flatten</id> |
| | | <phase>process-resources</phase> |
| | | <goals> |
| | | <goal>flatten</goal> |
| | | </goals> |
| | | </execution> |
| | | <execution> |
| | | <id>flatten.clean</id> |
| | | <phase>clean</phase> |
| | | <goals> |
| | | <goal>clean</goal> |
| | | </goals> |
| | | </execution> |
| | | </executions> |
| | | <configuration> |
| | | <updatePomFile>true</updatePomFile> |
| | | <flattenMode>resolveCiFriendliesOnly</flattenMode> |
| | | </configuration> |
| | | </plugin> |
| | | </plugins> |
| | | </build> |
| | | <profiles> |
| | | <profile> |
| | | <id>local</id> |
| | | <properties> |
| | | <monitor.username>ruoyi</monitor.username> |
| | | <profiles.active>local</profiles.active> |
| | | <monitor.password>123456</monitor.password> |
| | | <logging.level>info</logging.level> |
| | | </properties> |
| | | </profile> |
| | | <profile> |
| | | <id>dev</id> |
| | | <activation> |
| | | <activeByDefault>true</activeByDefault> |
| | | </activation> |
| | | <properties> |
| | | <monitor.username>ruoyi</monitor.username> |
| | | <profiles.active>dev</profiles.active> |
| | | <monitor.password>123456</monitor.password> |
| | | <logging.level>info</logging.level> |
| | | </properties> |
| | | </profile> |
| | | <profile> |
| | | <id>prod</id> |
| | | <properties> |
| | | <monitor.username>ruoyi</monitor.username> |
| | | <profiles.active>prod</profiles.active> |
| | | <monitor.password>123456</monitor.password> |
| | | <logging.level>warn</logging.level> |
| | | </properties> |
| | | </profile> |
| | | </profiles> |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | The MIT License (MIT) |
| | | |
| | | Copyright (c) 2019 RuoYi-Vue-Plus |
| | | |
| | | Permission is hereby granted, free of charge, to any person obtaining a copy of |
| | | this software and associated documentation files (the "Software"), to deal in |
| | | the Software without restriction, including without limitation the rights to |
| | | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of |
| | | the Software, and to permit persons to whom the Software is furnished to do so, |
| | | subject to the following conditions: |
| | | |
| | | The above copyright notice and this permission notice shall be included in all |
| | | copies or substantial portions of the Software. |
| | | |
| | | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| | | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
| | | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
| | | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
| | | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| | | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <img src="https://foruda.gitee.com/images/1679673773341074847/178e8451_1766278.png" width="50%" height="50%"> |
| | | <div style="height: 10px; clear: both;"></div> |
| | | |
| | | - - - |
| | | ## å¹³å°ç®ä» |
| | | |
| | | [](https://gitee.com/dromara/RuoYi-Vue-Plus) |
| | | [](https://github.com/dromara/RuoYi-Vue-Plus) |
| | | [](https://gitcode.com/dromara/RuoYi-Vue-Plus) |
| | | [](https://gitee.com/dromara/RuoYi-Vue-Plus/blob/5.X/LICENSE) |
| | | <br> |
| | | [](https://gitee.com/dromara/RuoYi-Vue-Plus) |
| | | []() |
| | | []() |
| | | []() |
| | | |
| | | > Dromara RuoYi-Vue-Plus æ¯éå RuoYi-Vue é对 `åå¸å¼é群ä¸å¤ç§æ·` åºæ¯å
¨æ¹ä½å级(ä¸å
¼å®¹åæ¡æ¶) |
| | | |
| | | > 项ç®ä»£ç ãææ¡£ å弿ºå
è´¹å¯åç¨ éµå¾ªå¼æºåè®®å¨é¡¹ç®ä¸ä¿ç弿ºåè®®æä»¶å³å¯<br> |
| | | æ´»å°èåå°è 为å
´è¶£è弿º 为å¦ä¹ è弿º ä¸ºè®©å¤§å®¶çæ£å¯ä»¥å¦å°ææ¯è弿º |
| | | |
| | | > ç³»ç»æ¼ç¤º: [ä¼ éé¨](https://plus-doc.dromara.org/#/common/demo_system) |
| | | |
| | | > 宿¹å端项ç®å°å: [gitee](https://gitee.com/JavaLionLi/plus-ui) - [github](https://github.com/JavaLionLi/plus-ui) - [gitcode](https://gitcode.com/dromara/plus-ui)<br> |
| | | > æåå端项ç®å°å: åºäºvben5 [ruoyi-plus-vben5](https://gitee.com/dapppp/ruoyi-plus-vben5)<br> |
| | | > æåå端项ç®å°å: åºäºsoybean [ruoyi-plus-soybean](https://gitee.com/xlsea/ruoyi-plus-soybean)<br> |
| | | > æå项ç®å°å: å é¤å¤ç§æ·ä¸å·¥ä½æµ [RuoYi-Vue-Plus-Single](https://gitee.com/ColorDreams/RuoYi-Vue-Plus-Single)<br> |
| | | |
| | | > ææ¡£å°å: [plus-doc](https://plus-doc.dromara.org) å½å
å é: [plus-doc.top](https://plus-doc.top) |
| | | |
| | | ## èµå©å |
| | | |
| | | MaxKey ä¸çé¢å
åç¹ç»å½äº§å - https://gitee.com/dromara/MaxKey <br> |
| | | CCFlow é©°èä½ä»£ç -æµç¨-表å - https://gitee.com/opencc/RuoYi-JFlow <br> |
| | | æ°èµç§æ 软件å®å¶å¼åAPPå°ç¨åºç - https://www.shuduokeji.com/ <br> |
| | | å¼è¿ä¿¡æ¯ 软件å¼åå¹³å° - https://www.jnpfsoft.com/index.html?from=plus-doc <br> |
| | | Mall4J é«è´¨éJavaååç³»ç» - https://www.mall4j.com/cn/?statId=11 <br> |
| | | aizuda flowlong 工使µ - https://gitee.com/aizuda/flowlong <br> |
| | | Ruoyi-Plus-Uniapp - https://ruoyi.plus <br> |
| | | Topiam IAM/IDaaS身份管çå¹³å° - https://www.topiam.cn/ <br> |
| | | |
| | | [å¦ä½æä¸ºèµå©å å 群èç³»ä½è
è¯¦è° æ¯æ¥PV2500-3000 IP1700-2500](https://plus-doc.dromara.org/#/common/add_group) |
| | | |
| | | # æ¬æ¡æ¶ä¸RuoYiçåè½å·®å¼ |
| | | |
| | | | åè½ | æ¬æ¡æ¶ | RuoYi | |
| | | |-------------|-------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------| |
| | | | åç«¯é¡¹ç® | éç¨ Vue3 + TS + ElementPlus éå | åºäºVue2/Vue3 + JS | |
| | | | å端项ç®ç»æ | éç¨æä»¶å + æ©å±å
å½¢å¼ ç»æè§£è¦ æäºæ©å± | 模åç¸äºæ³¨å
¥è¦å严éé¾ä»¥æ©å± | |
| | | | å端代ç 飿 ¼ | ä¸¥æ ¼éµå®Alibabaè§èä¸é¡¹ç®ç»ä¸é
ç½®çä»£ç æ ¼å¼å | 代ç 书åä¸å¸¸è§ç»æä¸åé
读éç¢å¤§ | |
| | | | Webå®¹å¨ | éç¨ Undertow åºäº XNIO ç髿§è½å®¹å¨ | éç¨ Tomcat | |
| | | | æéè®¤è¯ | éç¨ Sa-TokenãJwt éæä½¿ç¨åè½é½å
¨ ä½è¦å 髿©å± | Spring Security é
ç½®ç¹çæ©å±æ§æå·® | |
| | | | æé注解 | éç¨ Sa-Token æ¯ææ³¨è§£ ç»å½æ ¡éªãè§è²æ ¡éªãæéæ ¡éªãäºçº§è®¤è¯æ ¡éªãHttpBasicæ ¡éªãå¿½ç¥æ ¡éª<br/>è§è²ä¸æéæ ¡éªæ¯æå¤ç§æ¡ä»¶ å¦ `AND` `OR` æ `æé OR è§è²` çå¤æè¡¨è¾¾å¼ | åªæ¯ææ¯å¦åå¨å¹é
| |
| | | | 䏿¹é´æ | éç¨ JustAuth ç¬¬ä¸æ¹ç»å½ç»ä»¶ æ¯æå¾®ä¿¡ãééçæ°åç§ä¸æ¹è®¤è¯ | æ | |
| | | | å
³ç³»æ°æ®åºæ¯æ | åçæ¯æ MySQLãOracleãPostgreSQLãSQLServer<br/>å¯åæ¶ä½¿ç¨å¼æåæ¢(æ¯æå
¶ä» mybatis-plus æ¯æçæææ°æ®åº åªéè¦å¢å jdbcä¾èµå³å¯ä½¿ç¨ 达梦éä»çåææåæ¡ä¾) | æ¯æ MysqlãOracle 䏿¯æåæ¶ä½¿ç¨ã䏿¯æå¼æåæ¢ | |
| | | | ç¼åæ°æ®åº | æ¯æ Redis 5-7 æ¯æå¤§é¨åæ°åè½ç¹æ§ å¦ åå¸å¼éæµãåå¸å¼éå | Redis ç®å get set æ¯æ | |
| | | | Redis客æ·ç«¯ | éç¨ Redisson Redis宿¹æ¨è åºäºNettyç客æ·ç«¯å·¥å
·<br/>æ¯æRedis 90%以ä¸çå½ä»¤ åºå±ä¼åè§é¿å¾å¤ä¸æ£ç¡®çç¨æ³ ä¾å¦: keys被转æ¢ä¸ºscan<br/>æ¯æåæºãå¨å
µãå主é群ãå¤ä¸»éç¾¤çæ¨¡å¼ | Lettuce + RedisTemplate æ¯ææ¨¡å¼å° å·¥å
·ä½¿ç¨ç¹ç<br/>è¿æ¥æ± éç¨ common-pool Bugå¤ç»å¸¸æ§åºé®é¢ | |
| | | | ç¼å注解 | éç¨ Spring-Cache 注解 对å
¶æ©å±äºå®ç°æ¯æäºæ´å¤åè½<br/>ä¾å¦ è¿ææ¶é´ æå¤§ç©ºé²æ¶é´ ç»æå¤§é¿åº¦ç åªéä¸ä¸ªæ³¨è§£å³å¯å®ææ°æ®èªå¨ç¼å | éæå¨ç¼åRedis代ç é»è¾ | |
| | | | ORMæ¡æ¶ | éç¨ Mybatis-Plus åºäºå¯¹è±¡å ä¹ä¸ç¨åSQLå
¨javaæä½ åè½å¼ºå¤§æä»¶ä¼å¤<br/>ä¾å¦å¤ç§æ·æä»¶ å页æä»¶ ä¹è§éæä»¶çç | éç¨ Mybatis åºäºXMLéè¦æåSQL | |
| | | | SQLçæ§ | éç¨ p6spy å¯è¾åºå®æ´SQL䏿§è¡æ¶é´çæ§ | logè¾åº éæå¨æ¼æ¥sqlä¸åæ°æ æ³å¿«éæ¥çè°è¯é®é¢ | |
| | | | æ°æ®å页 | éç¨ Mybatis-Plus å页æä»¶<br/>æ¡æ¶å¯¹å
¶è¿è¡äºæ©å± 对象åå页对象 æ¯æå¤ç§æ¹å¼ä¼ å æ¯æåç«¯å¤æåº å¤ææåº | éç¨ PageHelper ä»
æ¯æåæ¥è¯¢å页 åæ°åªè½ä»paramä¼ åªè½åæåº åè½æ©å±æ§å·® ä½éªä¸å¥½ | |
| | | | æ°æ®æé | éç¨ Mybatis-Plus æä»¶ èªè¡åææ¼æ¥SQL æ æå¼è¿æ»¤<br/>åªé为Mapper设置好注解æ¡ä»¶ æ¯æå¤ç§èªå®ä¹ ä¸éäºé¨é¨è§è² | éç¨ æ³¨è§£+aop å®ç° åºäºé¨é¨è§è² çæçsqlå
¼å®¹æ§å·® 䏿¯æå
¶ä»ä¸å¡æ©å±<br/>çæsqlåéæå¨æ¼æ¥å°å
·ä½ä¸å¡sqlä¸ å¯¹äºå¤ä¸ªMapperæ¥è¯¢ä¸èµ·ä½ç¨ | |
| | | | æ°æ®è±æ | éç¨ æ³¨è§£ + jackson åºååæé´è±æ æ¯æä¸å模åä¸åçè±ææ¡ä»¶<br/>æ¯æå¤ç§çç¥ å¦èº«ä»½è¯ãææºå·ãå°åãé®ç®±ãé¶è¡å¡ç å¯èªè¡æ©å± | æ | |
| | | | æ°æ®å è§£å¯ | éç¨ æ³¨è§£ + mybatis æ¦æªå¨ 对ååæ°æ®æé´èªå¨å è§£å¯<br/>æ¯æå¤ç§çç¥ å¦BASE64ãAESãRSAãSM2ãSM4ç | æ | |
| | | | æ¥å£ä¼ è¾å å¯ | éç¨ å¨æ AES + RSA å å¯è¯·æ± body æ¯ä¸æ¬¡è¯·æ±ç§é¥é½ä¸å大å¹
度éä½å¯ç ´è§£æ§ | æ | |
| | | | æ°æ®ç¿»è¯ | éç¨ æ³¨è§£ + jackson åºååæé´å¨æä¿®æ¹æ°æ® æ°æ®è¿è¡ç¿»è¯<br/>æ¯æå¤ç§æ¨¡å¼: `æ å°ç¿»è¯` `ç´æ¥ç¿»è¯` `å
¶ä»æ©å±æ¡ä»¶ç¿»è¯` æ¥å£å两æ¥å³å¯å®æèªå®ä¹æ©å± å
ç½®å¤ç§ç¿»è¯å®ç° | æ | |
| | | | 夿°æ®æºæ¡æ¶ | éç¨ dynamic-datasource æ¯æå¸é¢å¤§é¨åæ°æ®åº<br/>éè¿ymlé
ç½®å³å¯å¨æç®¡ç弿ä¸åç§ç±»çæ°æ®åº ä¹å¯éè¿åç«¯é¡µé¢æ·»å æ°æ®æº<br/>æ¯æspel表达å¼ä»è¯·æ±å¤´åæ°çæ¡ä»¶åæ¢æ°æ®æº | åºäº druid æå¨ç¼å代ç é
ç½®æ°æ®æº é
ç½®ç¹ç æ¯ææ§å·® | |
| | | | 夿°æ®æºäºå¡ | éç¨ dynamic-datasource æ¯æå¤æ°æ®æºä¸åç§ç±»çæ°æ®åºäºå¡åæ» | 䏿¯æ | |
| | | | æ°æ®åºè¿æ¥æ± | éç¨ HikariCP Spring宿¹å
ç½®è¿æ¥æ± é
ç½®ç®å 以æ§è½ä¸ç¨³å®æ§é»åå¤©ä¸ | éç¨ druid bugä¼å¤ 社åºç»´æ¤å·® æ´»è·åº¦ä½ é
ç½®ä¼å¤ç¹çæ§è½ä¸è¬ | |
| | | | æ°æ®åºä¸»é® | éç¨ éªè±ID åºäºæ¶é´æ³ç æåºå¢é¿ å¯ä¸ID åä¹ä¸ç¨ä¸ºååºå表 æ°æ®å并主é®å²çªéå¤èåæ | éç¨ æ°æ®åºèªå¢ID æ¯ææ°æ®éæé 䏿¯æå¤æ°æ®æºä¸»é®å¯ä¸ | |
| | | | WebSocketåè®® | åºäº Spring å°è£
ç WebSocket åè®® æ©å±äºTokené´æä¸åå¸å¼ä¼è¯åæ¥ ä¸ååªæ¯åºäºåæºçåºç© | æ | |
| | | | SSEæ¨é | éç¨ Spring SSE å®ç° æ©å±äºTokené´æä¸åå¸å¼ä¼è¯åæ¥ | æ | |
| | | | åºåå | éç¨ Jackson Spring宿¹å
ç½®åºåå é è°±!!! | éç¨ fastjson bugjson è¿è¿é»å | |
| | | | åå¸å¼å¹ç | åèç¾å¢GTISé²éç³»ç»ç®åå®ç°(ç»èå¯çææ¡£) | æå¨ç¼å注解åºäºaopå®ç° | |
| | | | åå¸å¼é | éç¨ Lock4j åºå±åºäº Redisson | æ | |
| | | | åå¸å¼ä»»å¡è°åº¦ | éç¨ SnailJob å¤©çæ¯æåå¸å¼ ç»ä¸ç管çä¸å¿ æ¯æå¤ç§æ°æ®åº æ¯æåçéè¯DAG任塿µç | éç¨ Quartz åºäºæ°æ®åºéæ§è½å·® é群éè¦åå¾å¤é
ç½®ä¸æ¹é | |
| | | | æä»¶åå¨ | éç¨ Minio åå¸å¼æä»¶åå¨ å¤©çæ¯æå¤æºãå¤ç¡¬çãå¤åçãå¤å¯æ¬åå¨<br/>æ¯ææé管ç å®å
¨å¯é æä»¶å¯å å¯åå¨ | éç¨ æ¬æºæä»¶åå¨ æä»¶è£¸æ¼ æä¸¢å¤±æ³æ¼ 䏿¯æé群æåç¹æåº | |
| | | | äºåå¨ | éç¨ AWS S3 å议客æ·ç«¯ æ¯æ ä¸çãé¿éãè
¾è®¯ çä¸åæ¯æS3åè®®çåå®¶ | 䏿¯æ | |
| | | | çä¿¡ | éç¨ sms4j çä¿¡èåå
æ¯ææ°åç§çä¿¡åå®¶ åªéå¨ymlé
置好åå®¶å¯é¥å³å¯ä½¿ç¨ å¯å¤åå®¶å
±ç¨ | 䏿¯æ | |
| | | | é®ä»¶ | éç¨ mail-api éç¨åè®®æ¯æå¤§é¨åé®ä»¶åå | 䏿¯æ | |
| | | | æ¥å£ææ¡£ | éç¨ SpringDocãjavadoc æ æ³¨è§£é¶å
¥ä¾µåºäºjava注é<br/>åªéææ³¨éå好 æ éååä¸å¤§å çææ¡£æ³¨è§£äº | éç¨ Springfox å·²åæ¢ç»´æ¤ éè¦ç¼å大éçæ³¨è§£æ¥æ¯æææ¡£çæ | |
| | | | æ ¡éªæ¡æ¶ | éç¨ Validation æ¯ææ³¨è§£ä¸å·¥å
·ç±»æ ¡éª æ³¨è§£æ¯æå½é
å | ä»
æ¯ææ³¨è§£ 䏿³¨è§£ä¸æ¯æå½é
å | |
| | | | Excelæ¡æ¶ | éç¨ FastExcel(åAlibaba EasyExcel) åºäºæä»¶å<br/>æ¡æ¶å¯¹å
¶å¢å äºå¾å¤åè½ ä¾å¦ èªå¨åå¹¶ç¸åå
容 èªå¨æåå¸å± åå
¸ç¿»è¯ç | åºäº POI æåå®ç° åè½æé 夿 æ©å±æ§å·® | |
| | | | 工使µæ¯æ | æ¯æåç§å¤æå®¡æ¹ 转å å§æ´¾ å åç¾ ä¼ç¾ æç¾ ç¥¨ç¾ çåè½ | æ | |
| | | | å·¥å
·ç±»æ¡æ¶ | éç¨ HutoolãLombok ä¸ç¾ç§å·¥å
·è¦ç90%ç使ç¨éæ± åºäºæ³¨è§£èªå¨çæ get set çç®åæ¡æ¶å¤§é代ç | æåå·¥å
·ç¨³å®æ§å·®æåºé®é¢ å·¥å
·æ°éæé 代ç èè¿éèªå·±æå get set ç | |
| | | | çæ§æ¡æ¶ | éç¨ SpringBoot-Admin åºäºSpringBoot宿¹ actuator æ¢éæºå¶<br/>宿¶çæ§æå¡ç¶æ æ¡æ¶è¿ä¸ºå
¶æ©å±äºå¨çº¿æ¥å¿æ¥ççæ§ | æ | |
| | | | é¾è·¯è¿½è¸ª | éç¨ Apache SkyWalking è¿å¨ä¸ºè¯·æ±ä¸ç¥éå»åªäº å°åªåºäºé®é¢èç¦æ¼å<br/>ç¨äºå®å³å¯å®æ¶æ¥ç请æ±ç»è¿çæ¯ä¸å¤æ¯ä¸ä¸ªèç¹ | æ | |
| | | | 代ç çæå¨ | åªéè®¾è®¡å¥½è¡¨ç»æ ä¸é®çæææcrud代ç ä¸é¡µé¢<br/>éä½80%çå¼åé æç²¾å齿å
¥å°ä¸å¡è®¾è®¡ä¸<br/>æ¡æ¶ä¸ºå
¶éé
MPãSpringDocè§èå代ç åæ¶æ¯æå¨æå¤æ°æ®æºä»£ç çæ | 代ç çæåçç»æ åªæ¯æåæ°æ®æºçæ | |
| | | | é¨ç½²æ¹å¼ | æ¯æ Docker ç¼æ ä¸é®æå»ºææç¯å¢ 让å¼å人å仿¤ä¸å为æå»ºç¯å¢èç¦æ¼ | åçjaré¨ç½² å
¶ä»ç¯å¢éæå¨ä¸è½½å®è£
èªè¡æå»º | |
| | | | 项ç®è·¯å¾ä¿®æ¹ | æä¾è¯¦ç»çä¿®æ¹æ¹æ¡ææ¡£ 并为å
¶åäºä¸äºæ¹å¨ é常ç®åå³å¯ä¿®æ¹æèªå·±æ³è¦ç | éè¦åå¾å¤æ¹é ææ¡£è¯´ææé | |
| | | | å½é
å | åºäºè¯·æ±å¤´å¨æè¿åä¸åè¯ç§çææ¬å
容 å¼åé¾åº¦ä½ æå¯¹åºçå·¥å
·ç±» æ¯æå¤§é¨å注解å
容å½é
å | åªæä¾åºç¡åè½ å
¶ä»éèªè¡ç¼åæ©å± | |
| | | | 代ç å便µè¯ | æä¾å便µè¯ ä½¿ç¨æ¹å¼ç¼åæ¹æ³ä¸mavenå¤ç¯å¢åæµæä»¶ | åªæä¾åºç¡åè½ å
¶ä»éèªè¡ç¼åæ©å± | |
| | | | Demoæ¡ä¾ | æä¾æ¡æ¶åè½çå®é
ä½¿ç¨æ¡ä¾ åç¬ä¸ä¸ªæ¨¡åæä¾äºå¾å¤å¾å
¨ | æ | |
| | | |
| | | |
| | | ## æ¬æ¡æ¶ä¸RuoYiçä¸å¡å·®å¼ |
| | | |
| | | | ä¸å¡ | åè½è¯´æ | æ¬æ¡æ¶ | RuoYi | |
| | | |--------|----------------------------------------------------------------------|-----|------------------| |
| | | | ç§æ·ç®¡ç | ç³»ç»å
ç§æ·ç管ç å¦:ç§æ·å¥é¤ãè¿ææ¶é´ãç¨æ·æ°éãä¼ä¸ä¿¡æ¯ç | æ¯æ | æ | |
| | | | ç§æ·å¥é¤ç®¡ç | ç³»ç»å
ç§æ·æè½ä½¿ç¨çå¥é¤ç®¡ç å¦:å¥é¤å
æå
å«çèåç | æ¯æ | æ | |
| | | | 客æ·ç«¯ç®¡ç | ç³»ç»å
对æ¥çææå®¢æ·ç«¯ç®¡ç å¦: pc端ãå°ç¨åºç«¯ç<br>æ¯æå¨æææç»å½æ¹å¼ å¦: çä¿¡ç»å½ãå¯ç ç»å½ç æ¯æå¨ææ§å¶tokenæ¶æ | æ¯æ | æ | |
| | | | ç¨æ·ç®¡ç | ç¨æ·ç管çé
ç½® å¦:æ°å¢ç¨æ·ãåé
ç¨æ·æå±é¨é¨ãè§è²ãå²ä½ç | æ¯æ | æ¯æ | |
| | | | é¨é¨ç®¡ç | é
置系ç»ç»ç»æºæï¼å
¬å¸ãé¨é¨ãå°ç»ï¼ æ ç»æå±ç°æ¯ææ°æ®æé | æ¯æ | æ¯æ | |
| | | | å²ä½ç®¡ç | é
置系ç»ç¨æ·æå±æ
ä»»èå¡ | æ¯æ | æ¯æ | |
| | | | èå管ç | é
置系ç»èåãæä½æéãæé®æéæ è¯ç | æ¯æ | æ¯æ | |
| | | | è§è²ç®¡ç | è§è²èåæéåé
ã设置è§è²ææºæè¿è¡æ°æ®èå´æéåå | æ¯æ | æ¯æ | |
| | | | åå
¸ç®¡ç | 对系ç»ä¸ç»å¸¸ä½¿ç¨çä¸äºè¾ä¸ºåºå®çæ°æ®è¿è¡ç»´æ¤ | æ¯æ | æ¯æ | |
| | | | åæ°ç®¡ç | 对系ç»å¨æé
置常ç¨åæ° | æ¯æ | æ¯æ | |
| | | | éç¥å
¬å | ç³»ç»éç¥å
¬åä¿¡æ¯åå¸ç»´æ¤ | æ¯æ | æ¯æ | |
| | | | æä½æ¥å¿ | ç³»ç»æ£å¸¸æä½æ¥å¿è®°å½åæ¥è¯¢ ç³»ç»å¼å¸¸ä¿¡æ¯æ¥å¿è®°å½åæ¥è¯¢ | æ¯æ | æ¯æ | |
| | | | ç»å½æ¥å¿ | ç³»ç»ç»å½æ¥å¿è®°å½æ¥è¯¢å
å«ç»å½å¼å¸¸ | æ¯æ | æ¯æ | |
| | | | æä»¶ç®¡ç | ç³»ç»æä»¶å±ç¤ºãä¸ä¼ ãä¸è½½ãå é¤ç管ç | æ¯æ | æ | |
| | | | æä»¶é
置管ç | ç³»ç»æä»¶ä¸ä¼ ãä¸è½½æéè¦çé
置信æ¯å¨ææ·»å ãä¿®æ¹ãå é¤ç管ç | æ¯æ | æ | |
| | | | å¨çº¿ç¨æ·ç®¡ç | å·²ç»å½ç³»ç»çå¨çº¿ç¨æ·ä¿¡æ¯çæ§ä¸å¼ºå¶è¸¢åºæä½ | æ¯æ | æ¯æ | |
| | | | 宿¶ä»»å¡ | è¿è¡æ¥è¡¨ãä»»å¡ç®¡ç(æ·»å ãä¿®æ¹ãå é¤)ãæ¥å¿ç®¡çãæ§è¡å¨ç®¡çç | æ¯æ | ä»
æ¯æä»»å¡ä¸æ¥å¿ç®¡ç | |
| | | | 代ç çæ | 夿°æ®æºåå端代ç ççæï¼javaãhtmlãxmlãsqlï¼æ¯æCRUDä¸è½½ | æ¯æ | ä»
æ¯æåæ°æ®æº | |
| | | | ç³»ç»æ¥å£ | æ ¹æ®ä¸å¡ä»£ç èªå¨çæç¸å
³çapiæ¥å£ææ¡£ | æ¯æ | æ¯æ | |
| | | | æå¡çæ§ | çè§é群系ç»CPUãå
åãç£çãå æ ãå¨çº¿æ¥å¿ãSpringç¸å
³é
ç½®ç | æ¯æ | ä»
æ¯æåæºCPUãå
åãç£ççæ§ | |
| | | | ç¼åçæ§ | 对系ç»çç¼åä¿¡æ¯æ¥è¯¢ï¼å½ä»¤ç»è®¡çã | æ¯æ | æ¯æ | |
| | | | ä½¿ç¨æ¡ä¾ | ç³»ç»çä¸äºåè½æ¡ä¾ | æ¯æ | 䏿¯æ | |
| | | |
| | | ## åèææ¡£ |
| | | |
| | | ä½¿ç¨æ¡æ¶å请ä»ç»é
è¯»ææ¡£éç¹æ³¨æäºé¡¹ |
| | | <br> |
| | | >[åå§åé¡¹ç® å¿
ç](https://plus-doc.dromara.org/#/ruoyi-vue-plus/quickstart/init) |
| | | >>[https://plus-doc.dromara.org/#/ruoyi-vue-plus/quickstart/init](https://plus-doc.dromara.org/#/ruoyi-vue-plus/quickstart/init) |
| | | > |
| | | >[䏿 ä¸è§é¢ å
¥é¨å¿
ç](https://plus-doc.dromara.org/#/common/column) |
| | | >>[https://plus-doc.dromara.org/#/common/column](https://plus-doc.dromara.org/#/common/column) |
| | | > |
| | | >[é¨ç½²é¡¹ç® å¿
ç](https://plus-doc.dromara.org/#/ruoyi-vue-plus/quickstart/deploy) |
| | | >>[https://plus-doc.dromara.org/#/ruoyi-vue-plus/quickstart/deploy](https://plus-doc.dromara.org/#/ruoyi-vue-plus/quickstart/deploy) |
| | | > |
| | | >[å¦ä½å 群](https://plus-doc.dromara.org/#/common/add_group) |
| | | >>[https://plus-doc.dromara.org/#/common/add_group](https://plus-doc.dromara.org/#/common/add_group) |
| | | > |
| | | >[åèææ¡£ Wiki](https://plus-doc.dromara.org) |
| | | >>[https://plus-doc.dromara.org](https://plus-doc.dromara.org) |
| | | |
| | | ## è½¯ä»¶æ¶æå¾ |
| | | |
| | |  |
| | | |
| | | ## å¦ä½åä¸è´¡ç® |
| | | |
| | | [åä¸è´¡ç®çæ¹å¼ https://plus-doc.dromara.org/#/common/contribution](https://plus-doc.dromara.org/#/common/contribution) |
| | | |
| | | ## æç®ä½è
|
| | | ä½è
为å
¼èå弿º,å¹³æ¶è¿éè¦å·¥ä½,妿叮å°äºæ¨å¯ä»¥è¯·ä½è
å个çé¥ |
| | | <img src="https://foruda.gitee.com/images/1678975784848381069/d8661ed9_1766278.png" width="300px" height="450px" /> |
| | | <img src="https://foruda.gitee.com/images/1678975801230205215/6f96229d_1766278.png" width="300px" height="450px" /> |
| | | |
| | | ## æ¼ç¤ºå¾ä¾ |
| | | |
| | | | | | |
| | | |--------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------| |
| | | |  |  | |
| | | |  |  | |
| | | |  |  | |
| | | |  |  | |
| | | |  |  | |
| | | |  |  | |
| | | |  |  | |
| | | |  |  | |
| | | |  |  | |
| | | |  |  | |
| | | |  |  | |
| | | |  |  | |
| | | |  |  | |
| | | |  |  | |
| | | |  |  | |
| | | |  |  | |
| | | |  |  | |
| | | |  |  | |
| | | |  |  | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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> |
| | | |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-vue-plus</artifactId> |
| | | <version>${revision}</version> |
| | | |
| | | <name>RuoYi-Vue-Plus</name> |
| | | <url>https://gitee.com/dromara/RuoYi-Vue-Plus</url> |
| | | <description>Dromara RuoYi-Vue-Pluså¤ç§æ·ç®¡çç³»ç»</description> |
| | | |
| | | <properties> |
| | | <revision>5.5.3</revision> |
| | | <spring-boot.version>3.5.10</spring-boot.version> |
| | | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
| | | <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> |
| | | <java.version>17</java.version> |
| | | <mybatis.version>3.5.19</mybatis.version> |
| | | <springdoc.version>2.8.15</springdoc.version> |
| | | <therapi-javadoc.version>0.15.0</therapi-javadoc.version> |
| | | <fastexcel.version>1.3.0</fastexcel.version> |
| | | <velocity.version>2.3</velocity.version> |
| | | <satoken.version>1.44.0</satoken.version> |
| | | <mybatis-plus.version>3.5.16</mybatis-plus.version> |
| | | <p6spy.version>3.9.1</p6spy.version> |
| | | <hutool.version>5.8.43</hutool.version> |
| | | <spring-boot-admin.version>3.5.6</spring-boot-admin.version> |
| | | <redisson.version>3.52.0</redisson.version> |
| | | <lock4j.version>2.2.7</lock4j.version> |
| | | <dynamic-ds.version>4.3.1</dynamic-ds.version> |
| | | <snailjob.version>1.9.0</snailjob.version> |
| | | <mapstruct-plus.version>1.5.0</mapstruct-plus.version> |
| | | <mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version> |
| | | <lombok.version>1.18.42</lombok.version> |
| | | <bouncycastle.version>1.80</bouncycastle.version> |
| | | <justauth.version>1.16.7</justauth.version> |
| | | <!-- 离线IPå°åå®ä½åº --> |
| | | <ip2region.version>3.3.2</ip2region.version> |
| | | <!-- OSS é
ç½® --> |
| | | <aws.sdk.version>2.28.22</aws.sdk.version> |
| | | <!-- SMS é
ç½® --> |
| | | <sms4j.version>3.3.5</sms4j.version> |
| | | <!-- éå¶æ¡æ¶ä¸çfastjsonçæ¬ --> |
| | | <fastjson.version>1.2.83</fastjson.version> |
| | | <!-- é¢åè¿è¡æ¶çD-ORMä¾èµ --> |
| | | <anyline.version>8.7.3-20251210</anyline.version> |
| | | <!-- 工使µé
ç½® --> |
| | | <warm-flow.version>1.8.4</warm-flow.version> |
| | | |
| | | <!-- æä»¶çæ¬ --> |
| | | <maven-jar-plugin.version>3.4.2</maven-jar-plugin.version> |
| | | <maven-war-plugin.version>3.4.0</maven-war-plugin.version> |
| | | <maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version> |
| | | <maven-surefire-plugin.version>3.5.3</maven-surefire-plugin.version> |
| | | <flatten-maven-plugin.version>1.3.0</flatten-maven-plugin.version> |
| | | <!-- æå
é»è®¤è·³è¿æµè¯ --> |
| | | <skipTests>true</skipTests> |
| | | </properties> |
| | | |
| | | <profiles> |
| | | <profile> |
| | | <id>local</id> |
| | | <properties> |
| | | <!-- ç¯å¢æ è¯ï¼éè¦ä¸é
ç½®æä»¶çåç§°ç¸å¯¹åº --> |
| | | <profiles.active>local</profiles.active> |
| | | <logging.level>info</logging.level> |
| | | <monitor.username>ruoyi</monitor.username> |
| | | <monitor.password>123456</monitor.password> |
| | | </properties> |
| | | </profile> |
| | | <profile> |
| | | <id>dev</id> |
| | | <properties> |
| | | <!-- ç¯å¢æ è¯ï¼éè¦ä¸é
ç½®æä»¶çåç§°ç¸å¯¹åº --> |
| | | <profiles.active>dev</profiles.active> |
| | | <logging.level>info</logging.level> |
| | | <monitor.username>ruoyi</monitor.username> |
| | | <monitor.password>123456</monitor.password> |
| | | </properties> |
| | | <activation> |
| | | <!-- é»è®¤ç¯å¢ --> |
| | | <activeByDefault>true</activeByDefault> |
| | | </activation> |
| | | </profile> |
| | | <profile> |
| | | <id>prod</id> |
| | | <properties> |
| | | <profiles.active>prod</profiles.active> |
| | | <logging.level>warn</logging.level> |
| | | <monitor.username>ruoyi</monitor.username> |
| | | <monitor.password>123456</monitor.password> |
| | | </properties> |
| | | </profile> |
| | | </profiles> |
| | | |
| | | <!-- ä¾èµå£°æ --> |
| | | <dependencyManagement> |
| | | <dependencies> |
| | | |
| | | <!-- SpringBootçä¾èµé
ç½®--> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-dependencies</artifactId> |
| | | <version>${spring-boot.version}</version> |
| | | <type>pom</type> |
| | | <scope>import</scope> |
| | | </dependency> |
| | | |
| | | <!-- hutool çä¾èµé
ç½®--> |
| | | <dependency> |
| | | <groupId>cn.hutool</groupId> |
| | | <artifactId>hutool-bom</artifactId> |
| | | <version>${hutool.version}</version> |
| | | <type>pom</type> |
| | | <scope>import</scope> |
| | | </dependency> |
| | | |
| | | <!-- common çä¾èµé
ç½®--> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-bom</artifactId> |
| | | <version>${revision}</version> |
| | | <type>pom</type> |
| | | <scope>import</scope> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.springdoc</groupId> |
| | | <artifactId>springdoc-openapi-starter-webmvc-api</artifactId> |
| | | <version>${springdoc.version}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.github.therapi</groupId> |
| | | <artifactId>therapi-runtime-javadoc</artifactId> |
| | | <version>${therapi-javadoc.version}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.projectlombok</groupId> |
| | | <artifactId>lombok</artifactId> |
| | | <version>${lombok.version}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>cn.idev.excel</groupId> |
| | | <artifactId>fastexcel</artifactId> |
| | | <version>${fastexcel.version}</version> |
| | | </dependency> |
| | | |
| | | <!-- velocity代ç çæä½¿ç¨æ¨¡æ¿ --> |
| | | <dependency> |
| | | <groupId>org.apache.velocity</groupId> |
| | | <artifactId>velocity-engine-core</artifactId> |
| | | <version>${velocity.version}</version> |
| | | </dependency> |
| | | |
| | | <!-- Sa-Token æé认è¯, å¨çº¿ææ¡£ï¼http://sa-token.dev33.cn/ --> |
| | | <dependency> |
| | | <groupId>cn.dev33</groupId> |
| | | <artifactId>sa-token-spring-boot3-starter</artifactId> |
| | | <version>${satoken.version}</version> |
| | | </dependency> |
| | | <!-- Sa-Token æ´å jwt --> |
| | | <dependency> |
| | | <groupId>cn.dev33</groupId> |
| | | <artifactId>sa-token-jwt</artifactId> |
| | | <version>${satoken.version}</version> |
| | | <exclusions> |
| | | <exclusion> |
| | | <groupId>cn.hutool</groupId> |
| | | <artifactId>hutool-all</artifactId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>cn.dev33</groupId> |
| | | <artifactId>sa-token-core</artifactId> |
| | | <version>${satoken.version}</version> |
| | | </dependency> |
| | | |
| | | <!-- dynamic-datasource 夿°æ®æº--> |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>dynamic-datasource-spring-boot3-starter</artifactId> |
| | | <version>${dynamic-ds.version}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.mybatis</groupId> |
| | | <artifactId>mybatis</artifactId> |
| | | <version>${mybatis.version}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>mybatis-plus-spring-boot3-starter</artifactId> |
| | | <version>${mybatis-plus.version}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>mybatis-plus-jsqlparser</artifactId> |
| | | <version>${mybatis-plus.version}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>mybatis-plus-annotation</artifactId> |
| | | <version>${mybatis-plus.version}</version> |
| | | </dependency> |
| | | |
| | | <!-- sqlæ§è½åææä»¶ --> |
| | | <dependency> |
| | | <groupId>p6spy</groupId> |
| | | <artifactId>p6spy</artifactId> |
| | | <version>${p6spy.version}</version> |
| | | </dependency> |
| | | |
| | | <!-- AWS SDK for Java 2.x --> |
| | | <dependency> |
| | | <groupId>software.amazon.awssdk</groupId> |
| | | <artifactId>s3</artifactId> |
| | | <version>${aws.sdk.version}</version> |
| | | </dependency> |
| | | <!-- 客æ·ç«¯çæ§è½å¢å¼ºä¼ è¾ç®¡çå¨ --> |
| | | <dependency> |
| | | <groupId>software.amazon.awssdk</groupId> |
| | | <artifactId>s3-transfer-manager</artifactId> |
| | | <version>${aws.sdk.version}</version> |
| | | </dependency> |
| | | <!-- éç¨äº Netty ç客æ·ç«¯ --> |
| | | <dependency> |
| | | <groupId>software.amazon.awssdk</groupId> |
| | | <artifactId>netty-nio-client</artifactId> |
| | | <version>${aws.sdk.version}</version> |
| | | </dependency> |
| | | <!--çä¿¡sms4j--> |
| | | <dependency> |
| | | <groupId>org.dromara.sms4j</groupId> |
| | | <artifactId>sms4j-spring-boot-starter</artifactId> |
| | | <version>${sms4j.version}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>de.codecentric</groupId> |
| | | <artifactId>spring-boot-admin-starter-server</artifactId> |
| | | <version>${spring-boot-admin.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>de.codecentric</groupId> |
| | | <artifactId>spring-boot-admin-starter-client</artifactId> |
| | | <version>${spring-boot-admin.version}</version> |
| | | </dependency> |
| | | |
| | | <!--redisson--> |
| | | <dependency> |
| | | <groupId>org.redisson</groupId> |
| | | <artifactId>redisson-spring-boot-starter</artifactId> |
| | | <version>${redisson.version}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>lock4j-redisson-spring-boot-starter</artifactId> |
| | | <version>${lock4j.version}</version> |
| | | </dependency> |
| | | |
| | | <!-- SnailJob Client --> |
| | | <dependency> |
| | | <groupId>com.aizuda</groupId> |
| | | <artifactId>snail-job-client-starter</artifactId> |
| | | <version>${snailjob.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.aizuda</groupId> |
| | | <artifactId>snail-job-client-job-core</artifactId> |
| | | <version>${snailjob.version}</version> |
| | | </dependency> |
| | | |
| | | <!-- å å¯å
å¼å
¥ --> |
| | | <dependency> |
| | | <groupId>org.bouncycastle</groupId> |
| | | <artifactId>bcprov-jdk15to18</artifactId> |
| | | <version>${bouncycastle.version}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>io.github.linpeilie</groupId> |
| | | <artifactId>mapstruct-plus-spring-boot-starter</artifactId> |
| | | <version>${mapstruct-plus.version}</version> |
| | | </dependency> |
| | | |
| | | <!-- Warm-Flowå½äº§å·¥ä½æµå¼æ, å¨çº¿ææ¡£ï¼http://warm-flow.cn/ --> |
| | | <dependency> |
| | | <groupId>org.dromara.warm</groupId> |
| | | <artifactId>warm-flow-mybatis-plus-sb3-starter</artifactId> |
| | | <version>${warm-flow.version}</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara.warm</groupId> |
| | | <artifactId>warm-flow-plugin-ui-sb-web</artifactId> |
| | | <version>${warm-flow.version}</version> |
| | | </dependency> |
| | | |
| | | <!-- JustAuth çä¾èµé
ç½®--> |
| | | <dependency> |
| | | <groupId>me.zhyd.oauth</groupId> |
| | | <artifactId>JustAuth</artifactId> |
| | | <version>${justauth.version}</version> |
| | | </dependency> |
| | | |
| | | <!-- 离线IPå°åå®ä½åº ip2region --> |
| | | <dependency> |
| | | <groupId>org.lionsoul</groupId> |
| | | <artifactId>ip2region</artifactId> |
| | | <version>${ip2region.version}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.alibaba</groupId> |
| | | <artifactId>fastjson</artifactId> |
| | | <version>${fastjson.version}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-system</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-job</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-generator</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-demo</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-qa</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- 工使µæ¨¡å --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-workflow</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | </dependencyManagement> |
| | | |
| | | <modules> |
| | | <module>ruoyi-admin</module> |
| | | <module>ruoyi-common</module> |
| | | <module>ruoyi-extend</module> |
| | | <module>ruoyi-modules</module> |
| | | </modules> |
| | | <packaging>pom</packaging> |
| | | |
| | | <build> |
| | | <plugins> |
| | | <plugin> |
| | | <groupId>org.apache.maven.plugins</groupId> |
| | | <artifactId>maven-compiler-plugin</artifactId> |
| | | <version>${maven-compiler-plugin.version}</version> |
| | | <configuration> |
| | | <source>${java.version}</source> |
| | | <target>${java.version}</target> |
| | | <encoding>${project.build.sourceEncoding}</encoding> |
| | | <annotationProcessorPaths> |
| | | <path> |
| | | <groupId>com.github.therapi</groupId> |
| | | <artifactId>therapi-runtime-javadoc-scribe</artifactId> |
| | | <version>${therapi-javadoc.version}</version> |
| | | </path> |
| | | <path> |
| | | <groupId>org.projectlombok</groupId> |
| | | <artifactId>lombok</artifactId> |
| | | <version>${lombok.version}</version> |
| | | </path> |
| | | <path> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-configuration-processor</artifactId> |
| | | <version>${spring-boot.version}</version> |
| | | </path> |
| | | <path> |
| | | <groupId>io.github.linpeilie</groupId> |
| | | <artifactId>mapstruct-plus-processor</artifactId> |
| | | <version>${mapstruct-plus.version}</version> |
| | | </path> |
| | | <path> |
| | | <groupId>org.projectlombok</groupId> |
| | | <artifactId>lombok-mapstruct-binding</artifactId> |
| | | <version>${mapstruct-plus.lombok.version}</version> |
| | | </path> |
| | | </annotationProcessorPaths> |
| | | <compilerArgs> |
| | | <arg>-parameters</arg> |
| | | </compilerArgs> |
| | | </configuration> |
| | | </plugin> |
| | | <!-- åå
æµè¯ä½¿ç¨ --> |
| | | <plugin> |
| | | <groupId>org.apache.maven.plugins</groupId> |
| | | <artifactId>maven-surefire-plugin</artifactId> |
| | | <version>${maven-surefire-plugin.version}</version> |
| | | <configuration> |
| | | <argLine>-Dfile.encoding=UTF-8</argLine> |
| | | <!-- æ ¹æ®æå
ç¯å¢æ§è¡å¯¹åºç@Tagæµè¯æ¹æ³ --> |
| | | <groups>${profiles.active}</groups> |
| | | <!-- æé¤æ ç¾ --> |
| | | <excludedGroups>exclude</excludedGroups> |
| | | </configuration> |
| | | </plugin> |
| | | <!-- ç»ä¸çæ¬å·ç®¡ç --> |
| | | <plugin> |
| | | <groupId>org.codehaus.mojo</groupId> |
| | | <artifactId>flatten-maven-plugin</artifactId> |
| | | <version>${flatten-maven-plugin.version}</version> |
| | | <configuration> |
| | | <updatePomFile>true</updatePomFile> |
| | | <flattenMode>resolveCiFriendliesOnly</flattenMode> |
| | | </configuration> |
| | | <executions> |
| | | <execution> |
| | | <id>flatten</id> |
| | | <phase>process-resources</phase> |
| | | <goals> |
| | | <goal>flatten</goal> |
| | | </goals> |
| | | </execution> |
| | | <execution> |
| | | <id>flatten.clean</id> |
| | | <phase>clean</phase> |
| | | <goals> |
| | | <goal>clean</goal> |
| | | </goals> |
| | | </execution> |
| | | </executions> |
| | | </plugin> |
| | | </plugins> |
| | | <resources> |
| | | <resource> |
| | | <directory>src/main/resources</directory> |
| | | <!-- å
³éè¿æ»¤ --> |
| | | <filtering>false</filtering> |
| | | </resource> |
| | | <resource> |
| | | <directory>src/main/resources</directory> |
| | | <!-- å¼å
¥ææ å¹é
æä»¶è¿è¡è¿æ»¤ --> |
| | | <includes> |
| | | <include>application*</include> |
| | | <include>bootstrap*</include> |
| | | <include>banner*</include> |
| | | </includes> |
| | | <!-- å¯ç¨è¿æ»¤ å³è¯¥èµæºä¸çåéå°ä¼è¢«è¿æ»¤å¨ä¸ç弿¿æ¢ --> |
| | | <filtering>true</filtering> |
| | | </resource> |
| | | </resources> |
| | | </build> |
| | | |
| | | <repositories> |
| | | <repository> |
| | | <id>public</id> |
| | | <name>huawei nexus</name> |
| | | <url>https://mirrors.huaweicloud.com/repository/maven/</url> |
| | | <releases> |
| | | <enabled>true</enabled> |
| | | </releases> |
| | | </repository> |
| | | </repositories> |
| | | |
| | | <pluginRepositories> |
| | | <pluginRepository> |
| | | <id>public</id> |
| | | <name>huawei nexus</name> |
| | | <url>https://mirrors.huaweicloud.com/repository/maven/</url> |
| | | <releases> |
| | | <enabled>true</enabled> |
| | | </releases> |
| | | <snapshots> |
| | | <enabled>false</enabled> |
| | | </snapshots> |
| | | </pluginRepository> |
| | | </pluginRepositories> |
| | | |
| | | </project> |
| | | |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-vue-plus</artifactId> |
| | | <version>5.5.3</version> |
| | | </parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-admin</artifactId> |
| | | <version>5.5.3</version> |
| | | <description>webæå¡å
¥å£</description> |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.postgresql</groupId> |
| | | <artifactId>postgresql</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-doc</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-social</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-ratelimiter</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-mail</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-system</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-job</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-generator</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-demo</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-qa</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-workflow</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>de.codecentric</groupId> |
| | | <artifactId>spring-boot-admin-starter-client</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-test</artifactId> |
| | | <scope>test</scope> |
| | | </dependency> |
| | | </dependencies> |
| | | <build> |
| | | <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> |
| | | </goals> |
| | | </execution> |
| | | </executions> |
| | | </plugin> |
| | | <plugin> |
| | | <artifactId>maven-jar-plugin</artifactId> |
| | | <version>${maven-jar-plugin.version}</version> |
| | | </plugin> |
| | | <plugin> |
| | | <artifactId>maven-war-plugin</artifactId> |
| | | <version>${maven-war-plugin.version}</version> |
| | | <configuration> |
| | | <failOnMissingWebXml>false</failOnMissingWebXml> |
| | | <warName>${project.artifactId}</warName> |
| | | </configuration> |
| | | </plugin> |
| | | </plugins> |
| | | </build> |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # è´å°å®éªå®¤ Spring 宿¹æ¨èéå JDKä¸è½½å°å https://bell-sw.com/pages/downloads/ |
| | | FROM bellsoft/liberica-openjdk-rocky:17.0.16-cds |
| | | #FROM bellsoft/liberica-openjdk-rocky:21.0.8-cds |
| | | #FROM findepi/graalvm:java17-native |
| | | |
| | | LABEL maintainer="Lion Li" |
| | | |
| | | RUN mkdir -p /ruoyi/server/logs \ |
| | | /ruoyi/server/temp \ |
| | | /ruoyi/skywalking/agent |
| | | |
| | | WORKDIR /ruoyi/server |
| | | |
| | | ENV SERVER_PORT=8080 SNAIL_PORT=28080 LANG=C.UTF-8 LC_ALL=C.UTF-8 JAVA_OPTS="" |
| | | |
| | | EXPOSE ${SERVER_PORT} |
| | | # æ´é² snail job 客æ·ç«¯ç«¯å£ ç¨äºå®æ¶ä»»å¡è°åº¦ä¸å¿éä¿¡ |
| | | EXPOSE ${SNAIL_PORT} |
| | | |
| | | ADD ./target/ruoyi-admin.jar ./app.jar |
| | | |
| | | SHELL ["/bin/bash", "-c"] |
| | | |
| | | ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -Dserver.port=${SERVER_PORT} \ |
| | | -Dsnail-job.port=${SNAIL_PORT} \ |
| | | # åºç¨åç§° 妿æ³åºåé群èç¹çæ§ æ¹æä¸åçåç§°å³å¯ |
| | | #-Dskywalking.agent.service_name=ruoyi-server \ |
| | | #-javaagent:/ruoyi/skywalking/agent/skywalking-agent.jar \ |
| | | -XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC ${JAVA_OPTS} \ |
| | | -jar app.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"> |
| | | <parent> |
| | | <artifactId>ruoyi-vue-plus</artifactId> |
| | | <groupId>org.dromara</groupId> |
| | | <version>${revision}</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <packaging>jar</packaging> |
| | | <artifactId>ruoyi-admin</artifactId> |
| | | |
| | | <description> |
| | | webæå¡å
¥å£ |
| | | </description> |
| | | |
| | | <dependencies> |
| | | |
| | | <!-- Mysql驱å¨å
--> |
| | | <!-- <dependency>--> |
| | | <!-- <groupId>com.mysql</groupId>--> |
| | | <!-- <artifactId>mysql-connector-j</artifactId>--> |
| | | <!-- </dependency>--> |
| | | |
| | | <!-- <!– mpæ¯æçæ°æ®åºåæ¯æ åªéè¦å¢å 对åºçjdbcä¾èµå³å¯ –>--> |
| | | <!-- <!– Oracle –>--> |
| | | <!-- <dependency>--> |
| | | <!-- <groupId>com.oracle.database.jdbc</groupId>--> |
| | | <!-- <artifactId>ojdbc8</artifactId>--> |
| | | <!-- </dependency>--> |
| | | <!-- <!– å
¼å®¹oracleä½çæ¬ –>--> |
| | | <!-- <dependency>--> |
| | | <!-- <groupId>com.oracle.database.nls</groupId>--> |
| | | <!-- <artifactId>orai18n</artifactId>--> |
| | | <!-- </dependency>--> |
| | | <!-- PostgreSql --> |
| | | <dependency> |
| | | <groupId>org.postgresql</groupId> |
| | | <artifactId>postgresql</artifactId> |
| | | </dependency> |
| | | <!-- <!– SqlServer –>--> |
| | | <!-- <dependency>--> |
| | | <!-- <groupId>com.microsoft.sqlserver</groupId>--> |
| | | <!-- <artifactId>mssql-jdbc</artifactId>--> |
| | | <!-- </dependency>--> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-doc</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-social</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-ratelimiter</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-mail</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-system</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-job</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- 代ç çæ--> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-generator</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- demo模å --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-demo</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- è´¨éåææ¨¡å --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-qa</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- 工使µæ¨¡å --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-workflow</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>de.codecentric</groupId> |
| | | <artifactId>spring-boot-admin-starter-client</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-test</artifactId> |
| | | <scope>test</scope> |
| | | </dependency> |
| | | |
| | | <!-- skywalking æ´å logback --> |
| | | <!-- <dependency>--> |
| | | <!-- <groupId>org.apache.skywalking</groupId>--> |
| | | <!-- <artifactId>apm-toolkit-logback-1.x</artifactId>--> |
| | | <!-- <version>${ä¸ä½ çagentæ¢éçæ¬ä¿æä¸è´}</version>--> |
| | | <!-- </dependency>--> |
| | | <!-- <dependency>--> |
| | | <!-- <groupId>org.apache.skywalking</groupId>--> |
| | | <!-- <artifactId>apm-toolkit-trace</artifactId>--> |
| | | <!-- <version>${ä¸ä½ çagentæ¢éçæ¬ä¿æä¸è´}</version>--> |
| | | <!-- </dependency>--> |
| | | |
| | | </dependencies> |
| | | |
| | | <build> |
| | | <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> |
| | | </goals> |
| | | </execution> |
| | | </executions> |
| | | </plugin> |
| | | <plugin> |
| | | <groupId>org.apache.maven.plugins</groupId> |
| | | <artifactId>maven-jar-plugin</artifactId> |
| | | <version>${maven-jar-plugin.version}</version> |
| | | </plugin> |
| | | <plugin> |
| | | <groupId>org.apache.maven.plugins</groupId> |
| | | <artifactId>maven-war-plugin</artifactId> |
| | | <version>${maven-war-plugin.version}</version> |
| | | <configuration> |
| | | <failOnMissingWebXml>false</failOnMissingWebXml> |
| | | <warName>${project.artifactId}</warName> |
| | | </configuration> |
| | | </plugin> |
| | | </plugins> |
| | | </build> |
| | | |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara; |
| | | |
| | | import org.springframework.boot.SpringApplication; |
| | | import org.springframework.boot.autoconfigure.SpringBootApplication; |
| | | import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup; |
| | | |
| | | /** |
| | | * å¯å¨ç¨åº |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | |
| | | @SpringBootApplication |
| | | public class DromaraApplication { |
| | | |
| | | public static void main(String[] args) { |
| | | SpringApplication application = new SpringApplication(DromaraApplication.class); |
| | | application.setApplicationStartup(new BufferingApplicationStartup(2048)); |
| | | application.run(args); |
| | | System.out.println("(â¥â â¿â )ï¾ï¾ RuoYi-Vue-Pluså¯å¨æå á(´ڡ`á)ï¾"); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara; |
| | | |
| | | import org.springframework.boot.builder.SpringApplicationBuilder; |
| | | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; |
| | | |
| | | /** |
| | | * web容å¨ä¸è¿è¡é¨ç½² |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public class DromaraServletInitializer extends SpringBootServletInitializer { |
| | | |
| | | @Override |
| | | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { |
| | | return application.sources(DromaraApplication.class); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.web.controller; |
| | | |
| | | import cn.dev33.satoken.annotation.SaIgnore; |
| | | import cn.dev33.satoken.exception.NotLoginException; |
| | | import cn.dev33.satoken.stp.StpUtil; |
| | | import cn.hutool.core.codec.Base64; |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import me.zhyd.oauth.model.AuthResponse; |
| | | import me.zhyd.oauth.model.AuthUser; |
| | | import me.zhyd.oauth.request.AuthRequest; |
| | | import me.zhyd.oauth.utils.AuthStateUtils; |
| | | import org.dromara.common.core.constant.SystemConstants; |
| | | import org.dromara.common.core.domain.R; |
| | | import org.dromara.common.core.domain.model.LoginBody; |
| | | import org.dromara.common.core.domain.model.RegisterBody; |
| | | import org.dromara.common.core.domain.model.SocialLoginBody; |
| | | import org.dromara.common.core.utils.*; |
| | | import org.dromara.common.encrypt.annotation.ApiEncrypt; |
| | | import org.dromara.common.json.utils.JsonUtils; |
| | | import org.dromara.common.ratelimiter.annotation.RateLimiter; |
| | | import org.dromara.common.ratelimiter.enums.LimitType; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | import org.dromara.common.social.config.properties.SocialLoginConfigProperties; |
| | | import org.dromara.common.social.config.properties.SocialProperties; |
| | | import org.dromara.common.social.utils.SocialUtils; |
| | | import org.dromara.common.sse.dto.SseMessageDto; |
| | | import org.dromara.common.sse.utils.SseMessageUtils; |
| | | import org.dromara.common.tenant.helper.TenantHelper; |
| | | import org.dromara.system.domain.bo.SysTenantBo; |
| | | import org.dromara.system.domain.vo.SysClientVo; |
| | | import org.dromara.system.domain.vo.SysTenantVo; |
| | | import org.dromara.system.service.ISysClientService; |
| | | import org.dromara.system.service.ISysConfigService; |
| | | import org.dromara.system.service.ISysSocialService; |
| | | import org.dromara.system.service.ISysTenantService; |
| | | import org.dromara.web.domain.vo.LoginTenantVo; |
| | | import org.dromara.web.domain.vo.LoginVo; |
| | | import org.dromara.web.domain.vo.TenantListVo; |
| | | import org.dromara.web.service.IAuthStrategy; |
| | | import org.dromara.web.service.SysLoginService; |
| | | import org.dromara.web.service.SysRegisterService; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import java.net.URL; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.concurrent.ScheduledExecutorService; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * è®¤è¯ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Slf4j |
| | | @SaIgnore |
| | | @RequiredArgsConstructor |
| | | @RestController |
| | | @RequestMapping("/auth") |
| | | public class AuthController { |
| | | |
| | | private final SocialProperties socialProperties; |
| | | private final SysLoginService loginService; |
| | | private final SysRegisterService registerService; |
| | | private final ISysConfigService configService; |
| | | private final ISysTenantService tenantService; |
| | | private final ISysSocialService socialUserService; |
| | | private final ISysClientService clientService; |
| | | private final ScheduledExecutorService scheduledExecutorService; |
| | | |
| | | |
| | | /** |
| | | * ç»å½æ¹æ³ |
| | | * |
| | | * @param body ç»å½ä¿¡æ¯ |
| | | * @return ç»æ |
| | | */ |
| | | @ApiEncrypt |
| | | @PostMapping("/login") |
| | | public R<LoginVo> login(@RequestBody String body) { |
| | | LoginBody loginBody = JsonUtils.parseObject(body, LoginBody.class); |
| | | ValidatorUtils.validate(loginBody); |
| | | // ææç±»åå客æ·ç«¯id |
| | | String clientId = loginBody.getClientId(); |
| | | String grantType = loginBody.getGrantType(); |
| | | SysClientVo client = clientService.queryByClientId(clientId); |
| | | // æ¥è¯¢ä¸å° client æ client å
ä¸å
å« grantType |
| | | if (ObjectUtil.isNull(client) || !StringUtils.contains(client.getGrantType(), grantType)) { |
| | | log.info("客æ·ç«¯id: {} 认è¯ç±»åï¼{} å¼å¸¸!.", clientId, grantType); |
| | | return R.fail(MessageUtils.message("auth.grant.type.error")); |
| | | } else if (!SystemConstants.NORMAL.equals(client.getStatus())) { |
| | | return R.fail(MessageUtils.message("auth.grant.type.blocked")); |
| | | } |
| | | // æ ¡éªç§æ· |
| | | loginService.checkTenant(loginBody.getTenantId()); |
| | | // ç»å½ |
| | | LoginVo loginVo = IAuthStrategy.login(body, client, grantType); |
| | | |
| | | Long userId = LoginHelper.getUserId(); |
| | | scheduledExecutorService.schedule(() -> { |
| | | SseMessageDto dto = new SseMessageDto(); |
| | | dto.setMessage(DateUtils.getTodayHour(new Date()) + "å¥½ï¼æ¬¢è¿ç»å½ è´¨éåæç®¡çç³»ç»"); |
| | | dto.setUserIds(List.of(userId)); |
| | | SseMessageUtils.publishMessage(dto); |
| | | }, 5, TimeUnit.SECONDS); |
| | | return R.ok(loginVo); |
| | | } |
| | | |
| | | /** |
| | | * è·å跳转URL |
| | | * |
| | | * @param source ç»å½æ¥æº |
| | | * @return ç»æ |
| | | */ |
| | | @GetMapping("/binding/{source}") |
| | | public R<String> authBinding(@PathVariable("source") String source, |
| | | @RequestParam String tenantId, @RequestParam String domain) { |
| | | SocialLoginConfigProperties obj = socialProperties.getType().get(source); |
| | | if (ObjectUtil.isNull(obj)) { |
| | | return R.fail(source + "å¹³å°è´¦å·æä¸æ¯æ"); |
| | | } |
| | | AuthRequest authRequest = SocialUtils.getAuthRequest(source, socialProperties); |
| | | Map<String, String> map = new HashMap<>(); |
| | | map.put("tenantId", tenantId); |
| | | map.put("domain", domain); |
| | | map.put("state", AuthStateUtils.createState()); |
| | | String authorizeUrl = authRequest.authorize(Base64.encode(JsonUtils.toJsonString(map), StandardCharsets.UTF_8)); |
| | | return R.ok("æä½æå", authorizeUrl); |
| | | } |
| | | |
| | | /** |
| | | * å端åè°ç»å®ææ(éè¦token) |
| | | * |
| | | * @param loginBody 请æ±ä½ |
| | | * @return ç»æ |
| | | */ |
| | | @PostMapping("/social/callback") |
| | | public R<Void> socialCallback(@RequestBody SocialLoginBody loginBody) { |
| | | // æ ¡éªtoken |
| | | StpUtil.checkLogin(); |
| | | // è·åç¬¬ä¸æ¹ç»å½ä¿¡æ¯ |
| | | AuthResponse<AuthUser> response = SocialUtils.loginAuth( |
| | | loginBody.getSource(), loginBody.getSocialCode(), |
| | | loginBody.getSocialState(), socialProperties); |
| | | AuthUser authUserData = response.getData(); |
| | | // 夿ææååºæ¯å¦æå |
| | | if (!response.ok()) { |
| | | return R.fail(response.getMsg()); |
| | | } |
| | | loginService.socialRegister(authUserData); |
| | | return R.ok(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * åæ¶ææ(éè¦token) |
| | | * |
| | | * @param socialId socialId |
| | | */ |
| | | @DeleteMapping(value = "/unlock/{socialId}") |
| | | public R<Void> unlockSocial(@PathVariable Long socialId) { |
| | | // æ ¡éªtoken |
| | | StpUtil.checkLogin(); |
| | | Boolean rows = socialUserService.deleteWithValidById(socialId); |
| | | return rows ? R.ok() : R.fail("åæ¶ææå¤±è´¥"); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * éåºç»å½ |
| | | */ |
| | | @PostMapping("/logout") |
| | | public R<Void> logout() { |
| | | loginService.logout(); |
| | | return R.ok("éåºæå"); |
| | | } |
| | | |
| | | /** |
| | | * ç¨æ·æ³¨å |
| | | */ |
| | | @ApiEncrypt |
| | | @PostMapping("/register") |
| | | public R<Void> register(@Validated @RequestBody RegisterBody user) { |
| | | if (!configService.selectRegisterEnabled(user.getTenantId())) { |
| | | return R.fail("å½åç³»ç»æ²¡æå¼å¯æ³¨ååè½ï¼"); |
| | | } |
| | | registerService.register(user); |
| | | return R.ok(); |
| | | } |
| | | |
| | | /** |
| | | * ç»å½é¡µé¢ç§æ·ä¸ææ¡ |
| | | * |
| | | * @return ç§æ·å表 |
| | | */ |
| | | @RateLimiter(time = 60, count = 20, limitType = LimitType.IP) |
| | | @GetMapping("/tenant/list") |
| | | public R<LoginTenantVo> tenantList(HttpServletRequest request) throws Exception { |
| | | // è¿å对象 |
| | | LoginTenantVo result = new LoginTenantVo(); |
| | | boolean enable = TenantHelper.isEnable(); |
| | | result.setTenantEnabled(enable); |
| | | // 妿æªå¼å¯ç§æ·è¿ç´æ¥è¿å |
| | | if (!enable) { |
| | | return R.ok(result); |
| | | } |
| | | |
| | | List<SysTenantVo> tenantList = tenantService.queryList(new SysTenantBo()); |
| | | List<TenantListVo> voList = MapstructUtils.convert(tenantList, TenantListVo.class); |
| | | try { |
| | | // 妿åªè¶
管è¿åææç§æ· |
| | | if (LoginHelper.isSuperAdmin()) { |
| | | result.setVoList(voList); |
| | | return R.ok(result); |
| | | } |
| | | } catch (NotLoginException ignored) { |
| | | } |
| | | |
| | | // è·ååå |
| | | String host; |
| | | String referer = request.getHeader("referer"); |
| | | if (StringUtils.isNotBlank(referer)) { |
| | | // è¿éä»refererä¸å弿¯ä¸ºäºæ¬å°ä½¿ç¨hostsæ·»å èæååï¼æ¹ä¾¿æ¬å°ç¯å¢è°è¯ |
| | | host = referer.split("//")[1].split("/")[0]; |
| | | } else { |
| | | host = new URL(request.getRequestURL().toString()).getHost(); |
| | | } |
| | | // æ ¹æ®ååè¿è¡çé |
| | | List<TenantListVo> list = StreamUtils.filter(voList, vo -> |
| | | StringUtils.equalsIgnoreCase(vo.getDomain(), host)); |
| | | result.setVoList(CollUtil.isNotEmpty(list) ? list : voList); |
| | | return R.ok(result); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.web.controller; |
| | | |
| | | import cn.dev33.satoken.annotation.SaIgnore; |
| | | import cn.hutool.captcha.generator.CodeGenerator; |
| | | import cn.hutool.captcha.generator.MathGenerator; |
| | | import cn.hutool.captcha.generator.RandomGenerator; |
| | | import cn.hutool.core.util.IdUtil; |
| | | import cn.hutool.core.util.RandomUtil; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.core.constant.Constants; |
| | | import org.dromara.common.core.constant.GlobalConstants; |
| | | import org.dromara.common.core.domain.R; |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.mail.config.properties.MailProperties; |
| | | import org.dromara.common.mail.utils.MailUtils; |
| | | import org.dromara.common.ratelimiter.annotation.RateLimiter; |
| | | import org.dromara.common.ratelimiter.enums.LimitType; |
| | | import org.dromara.common.redis.utils.RedisUtils; |
| | | import org.dromara.common.web.core.WaveAndCircleCaptcha; |
| | | import org.dromara.common.web.config.properties.CaptchaProperties; |
| | | import org.dromara.sms4j.api.SmsBlend; |
| | | import org.dromara.sms4j.api.entity.SmsResponse; |
| | | import org.dromara.sms4j.core.factory.SmsFactory; |
| | | import org.dromara.web.domain.vo.CaptchaVo; |
| | | import org.springframework.expression.Expression; |
| | | import org.springframework.expression.ExpressionParser; |
| | | import org.springframework.expression.spel.standard.SpelExpressionParser; |
| | | import org.springframework.validation.annotation.Validated; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import java.awt.*; |
| | | import java.time.Duration; |
| | | import java.util.LinkedHashMap; |
| | | |
| | | /** |
| | | * éªè¯ç æä½å¤ç |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @SaIgnore |
| | | @Slf4j |
| | | @Validated |
| | | @RequiredArgsConstructor |
| | | @RestController |
| | | public class CaptchaController { |
| | | |
| | | private final CaptchaProperties captchaProperties; |
| | | private final MailProperties mailProperties; |
| | | |
| | | /** |
| | | * çä¿¡éªè¯ç |
| | | * |
| | | * @param phonenumber ç¨æ·ææºå· |
| | | */ |
| | | @RateLimiter(key = "#phonenumber", time = 60, count = 1) |
| | | @GetMapping("/resource/sms/code") |
| | | public R<Void> smsCode(@NotBlank(message = "{user.phonenumber.not.blank}") String phonenumber) { |
| | | String key = GlobalConstants.CAPTCHA_CODE_KEY + phonenumber; |
| | | String code = RandomUtil.randomNumbers(4); |
| | | RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION)); |
| | | // éªè¯ç 模æ¿id èªè¡å¤ç (æ¥æ°æ®åºæåæ»åå¯) |
| | | String templateId = ""; |
| | | LinkedHashMap<String, String> map = new LinkedHashMap<>(1); |
| | | map.put("code", code); |
| | | SmsBlend smsBlend = SmsFactory.getSmsBlend("config1"); |
| | | SmsResponse smsResponse = smsBlend.sendMessage(phonenumber, templateId, map); |
| | | if (!smsResponse.isSuccess()) { |
| | | log.error("éªè¯ç çä¿¡åéå¼å¸¸ => {}", smsResponse); |
| | | return R.fail(smsResponse.getData().toString()); |
| | | } |
| | | return R.ok(); |
| | | } |
| | | |
| | | /** |
| | | * é®ç®±éªè¯ç |
| | | * |
| | | * @param email é®ç®± |
| | | */ |
| | | @GetMapping("/resource/email/code") |
| | | public R<Void> emailCode(@NotBlank(message = "{user.email.not.blank}") String email) { |
| | | if (!mailProperties.getEnabled()) { |
| | | return R.fail("å½åç³»ç»æ²¡æå¼å¯é®ç®±åè½ï¼"); |
| | | } |
| | | SpringUtils.getAopProxy(this).emailCodeImpl(email); |
| | | return R.ok(); |
| | | } |
| | | |
| | | /** |
| | | * é®ç®±éªè¯ç |
| | | * ç¬ç«æ¹æ³é¿å
éªè¯ç å
³éä¹åä»ç¶èµ°éæµ |
| | | */ |
| | | @RateLimiter(key = "#email", time = 60, count = 1) |
| | | public void emailCodeImpl(String email) { |
| | | String key = GlobalConstants.CAPTCHA_CODE_KEY + email; |
| | | String code = RandomUtil.randomNumbers(4); |
| | | RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION)); |
| | | try { |
| | | MailUtils.sendText(email, "ç»å½éªè¯ç ", "æ¨æ¬æ¬¡éªè¯ç 为ï¼" + code + "ï¼æææ§ä¸º" + Constants.CAPTCHA_EXPIRATION + "åéï¼è¯·å°½å¿«å¡«åã"); |
| | | } catch (Exception e) { |
| | | log.error("éªè¯ç çä¿¡åéå¼å¸¸ => {}", e.getMessage()); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * çæéªè¯ç |
| | | */ |
| | | @GetMapping("/auth/code") |
| | | public R<CaptchaVo> getCode() { |
| | | boolean captchaEnabled = captchaProperties.getEnable(); |
| | | if (!captchaEnabled) { |
| | | CaptchaVo captchaVo = new CaptchaVo(); |
| | | captchaVo.setCaptchaEnabled(false); |
| | | return R.ok(captchaVo); |
| | | } |
| | | return R.ok(SpringUtils.getAopProxy(this).getCodeImpl()); |
| | | } |
| | | |
| | | /** |
| | | * çæéªè¯ç |
| | | * ç¬ç«æ¹æ³é¿å
éªè¯ç å
³éä¹åä»ç¶èµ°éæµ |
| | | */ |
| | | @RateLimiter(time = 60, count = 10, limitType = LimitType.IP) |
| | | public CaptchaVo getCodeImpl() { |
| | | // ä¿åéªè¯ç ä¿¡æ¯ |
| | | String uuid = IdUtil.simpleUUID(); |
| | | String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + uuid; |
| | | // çæéªè¯ç |
| | | String captchaType = captchaProperties.getType(); |
| | | CodeGenerator codeGenerator; |
| | | if ("math".equals(captchaType)) { |
| | | codeGenerator = new MathGenerator(captchaProperties.getNumberLength(), false); |
| | | } else { |
| | | codeGenerator = new RandomGenerator(captchaProperties.getCharLength()); |
| | | } |
| | | WaveAndCircleCaptcha captcha = new WaveAndCircleCaptcha(160, 60); |
| | | // captcha.setBackground(Color.WHITE); // ä¸è®¾ç½®å°±æ¯éæåº |
| | | captcha.setFont(new Font("Arial", Font.BOLD, 45)); |
| | | captcha.setGenerator(codeGenerator); |
| | | captcha.createCode(); |
| | | // å¦ææ¯æ°å¦éªè¯ç ï¼ä½¿ç¨SpEL表达å¼å¤çéªè¯ç ç»æ |
| | | String code = captcha.getCode(); |
| | | if ("math".equals(captchaType)) { |
| | | ExpressionParser parser = new SpelExpressionParser(); |
| | | Expression exp = parser.parseExpression(StringUtils.remove(code, "=")); |
| | | code = exp.getValue(String.class); |
| | | } |
| | | RedisUtils.setCacheObject(verifyKey, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION)); |
| | | CaptchaVo captchaVo = new CaptchaVo(); |
| | | captchaVo.setUuid(uuid); |
| | | captchaVo.setImg(captcha.getImageBase64()); |
| | | return captchaVo; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.web.controller; |
| | | |
| | | import cn.dev33.satoken.annotation.SaIgnore; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | /** |
| | | * é¦é¡µ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @SaIgnore |
| | | @RequiredArgsConstructor |
| | | @RestController |
| | | public class IndexController { |
| | | |
| | | /** |
| | | * 访é®é¦é¡µï¼æç¤ºè¯ |
| | | */ |
| | | @GetMapping("/") |
| | | public String index() { |
| | | return StringUtils.format("欢è¿ä½¿ç¨{}åå°ç®¡çæ¡æ¶ï¼è¯·éè¿å端å°å访é®ã", SpringUtils.getApplicationName()); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.web.domain.vo; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * éªè¯ç ä¿¡æ¯ |
| | | * |
| | | * @author Michelle.Chung |
| | | */ |
| | | @Data |
| | | public class CaptchaVo { |
| | | |
| | | /** |
| | | * æ¯å¦å¼å¯éªè¯ç |
| | | */ |
| | | private Boolean captchaEnabled = true; |
| | | |
| | | private String uuid; |
| | | |
| | | /** |
| | | * éªè¯ç å¾ç |
| | | */ |
| | | private String img; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.web.domain.vo; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * ç»å½ç§æ·å¯¹è±¡ |
| | | * |
| | | * @author Michelle.Chung |
| | | */ |
| | | @Data |
| | | public class LoginTenantVo { |
| | | |
| | | /** |
| | | * ç§æ·å¼å
³ |
| | | */ |
| | | private Boolean tenantEnabled; |
| | | |
| | | /** |
| | | * ç§æ·å¯¹è±¡å表 |
| | | */ |
| | | private List<TenantListVo> voList; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.web.domain.vo; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonProperty; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * ç»å½éªè¯ä¿¡æ¯ |
| | | * |
| | | * @author Michelle.Chung |
| | | */ |
| | | @Data |
| | | public class LoginVo { |
| | | |
| | | /** |
| | | * ææä»¤ç |
| | | */ |
| | | @JsonProperty("access_token") |
| | | private String accessToken; |
| | | |
| | | /** |
| | | * å·æ°ä»¤ç |
| | | */ |
| | | @JsonProperty("refresh_token") |
| | | private String refreshToken; |
| | | |
| | | /** |
| | | * ææä»¤ç access_token çæææ |
| | | */ |
| | | @JsonProperty("expire_in") |
| | | private Long expireIn; |
| | | |
| | | /** |
| | | * å·æ°ä»¤ç refresh_token çæææ |
| | | */ |
| | | @JsonProperty("refresh_expire_in") |
| | | private Long refreshExpireIn; |
| | | |
| | | /** |
| | | * åºç¨id |
| | | */ |
| | | @JsonProperty("client_id") |
| | | private String clientId; |
| | | |
| | | /** |
| | | * 令çæé |
| | | */ |
| | | private String scope; |
| | | |
| | | /** |
| | | * ç¨æ· openid |
| | | */ |
| | | private String openid; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.web.domain.vo; |
| | | |
| | | import org.dromara.system.domain.vo.SysTenantVo; |
| | | import io.github.linpeilie.annotations.AutoMapper; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * ç§æ·å表 |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Data |
| | | @AutoMapper(target = SysTenantVo.class) |
| | | public class TenantListVo { |
| | | |
| | | /** |
| | | * ç§æ·ç¼å· |
| | | */ |
| | | private String tenantId; |
| | | |
| | | /** |
| | | * ä¼ä¸åç§° |
| | | */ |
| | | private String companyName; |
| | | |
| | | /** |
| | | * åå |
| | | */ |
| | | private String domain; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.web.listener; |
| | | |
| | | import cn.dev33.satoken.listener.SaTokenListener; |
| | | import cn.dev33.satoken.stp.StpUtil; |
| | | import cn.dev33.satoken.stp.parameter.SaLoginParameter; |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.http.useragent.UserAgent; |
| | | import cn.hutool.http.useragent.UserAgentUtil; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.core.constant.CacheConstants; |
| | | import org.dromara.common.core.constant.Constants; |
| | | import org.dromara.common.core.domain.dto.UserOnlineDTO; |
| | | import org.dromara.common.core.utils.MessageUtils; |
| | | import org.dromara.common.core.utils.ServletUtils; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.dromara.common.core.utils.ip.AddressUtils; |
| | | import org.dromara.common.log.event.LogininforEvent; |
| | | import org.dromara.common.redis.utils.RedisUtils; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | import org.dromara.common.tenant.helper.TenantHelper; |
| | | import org.dromara.web.service.SysLoginService; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.time.Duration; |
| | | |
| | | /** |
| | | * ç¨æ·è¡ä¸º 侦å¬å¨çå®ç° |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @Component |
| | | @Slf4j |
| | | public class UserActionListener implements SaTokenListener { |
| | | |
| | | private final SysLoginService loginService; |
| | | |
| | | /** |
| | | * æ¯æ¬¡ç»å½æ¶è§¦å |
| | | */ |
| | | @Override |
| | | public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginParameter loginParameter) { |
| | | UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent")); |
| | | String ip = ServletUtils.getClientIP(); |
| | | UserOnlineDTO dto = new UserOnlineDTO(); |
| | | dto.setIpaddr(ip); |
| | | dto.setLoginLocation(AddressUtils.getRealAddressByIP(ip)); |
| | | dto.setBrowser(userAgent.getBrowser().getName()); |
| | | dto.setOs(userAgent.getOs().getName()); |
| | | dto.setLoginTime(System.currentTimeMillis()); |
| | | dto.setTokenId(tokenValue); |
| | | String username = (String) loginParameter.getExtra(LoginHelper.USER_NAME_KEY); |
| | | String tenantId = (String) loginParameter.getExtra(LoginHelper.TENANT_KEY); |
| | | dto.setUserName(username); |
| | | dto.setClientKey((String) loginParameter.getExtra(LoginHelper.CLIENT_KEY)); |
| | | dto.setDeviceType(loginParameter.getDeviceType()); |
| | | dto.setDeptName((String) loginParameter.getExtra(LoginHelper.DEPT_NAME_KEY)); |
| | | TenantHelper.dynamic(tenantId, () -> { |
| | | if(loginParameter.getTimeout() == -1) { |
| | | RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto); |
| | | } else { |
| | | RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto, Duration.ofSeconds(loginParameter.getTimeout())); |
| | | } |
| | | }); |
| | | // è®°å½ç»å½æ¥å¿ |
| | | LogininforEvent logininforEvent = new LogininforEvent(); |
| | | logininforEvent.setTenantId(tenantId); |
| | | logininforEvent.setUsername(username); |
| | | logininforEvent.setStatus(Constants.LOGIN_SUCCESS); |
| | | logininforEvent.setMessage(MessageUtils.message("user.login.success")); |
| | | logininforEvent.setRequest(ServletUtils.getRequest()); |
| | | SpringUtils.context().publishEvent(logininforEvent); |
| | | // æ´æ°ç»å½ä¿¡æ¯ |
| | | loginService.recordLoginInfo((Long) loginParameter.getExtra(LoginHelper.USER_KEY), ip); |
| | | log.info("user doLogin, userId:{}, token:{}", loginId, tokenValue); |
| | | } |
| | | |
| | | /** |
| | | * æ¯æ¬¡æ³¨éæ¶è§¦å |
| | | */ |
| | | @Override |
| | | public void doLogout(String loginType, Object loginId, String tokenValue) { |
| | | String tenantId = Convert.toStr(StpUtil.getExtra(tokenValue, LoginHelper.TENANT_KEY)); |
| | | TenantHelper.dynamic(tenantId, () -> { |
| | | RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); |
| | | }); |
| | | log.info("user doLogout, userId:{}, token:{}", loginId, tokenValue); |
| | | } |
| | | |
| | | /** |
| | | * æ¯æ¬¡è¢«è¸¢ä¸çº¿æ¶è§¦å |
| | | */ |
| | | @Override |
| | | public void doKickout(String loginType, Object loginId, String tokenValue) { |
| | | String tenantId = Convert.toStr(StpUtil.getExtra(tokenValue, LoginHelper.TENANT_KEY)); |
| | | TenantHelper.dynamic(tenantId, () -> { |
| | | RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); |
| | | }); |
| | | log.info("user doKickout, userId:{}, token:{}", loginId, tokenValue); |
| | | } |
| | | |
| | | /** |
| | | * æ¯æ¬¡è¢«é¡¶ä¸çº¿æ¶è§¦å |
| | | */ |
| | | @Override |
| | | public void doReplaced(String loginType, Object loginId, String tokenValue) { |
| | | String tenantId = Convert.toStr(StpUtil.getExtra(tokenValue, LoginHelper.TENANT_KEY)); |
| | | TenantHelper.dynamic(tenantId, () -> { |
| | | RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); |
| | | }); |
| | | log.info("user doReplaced, userId:{}, token:{}", loginId, tokenValue); |
| | | } |
| | | |
| | | /** |
| | | * æ¯æ¬¡è¢«å°ç¦æ¶è§¦å |
| | | */ |
| | | @Override |
| | | public void doDisable(String loginType, Object loginId, String service, int level, long disableTime) { |
| | | } |
| | | |
| | | /** |
| | | * æ¯æ¬¡è¢«è§£å°æ¶è§¦å |
| | | */ |
| | | @Override |
| | | public void doUntieDisable(String loginType, Object loginId, String service) { |
| | | } |
| | | |
| | | /** |
| | | * æ¯æ¬¡æå¼äºçº§è®¤è¯æ¶è§¦å |
| | | */ |
| | | @Override |
| | | public void doOpenSafe(String loginType, String tokenValue, String service, long safeTime) { |
| | | } |
| | | |
| | | /** |
| | | * æ¯æ¬¡å建Sessionæ¶è§¦å |
| | | */ |
| | | @Override |
| | | public void doCloseSafe(String loginType, String tokenValue, String service) { |
| | | } |
| | | |
| | | /** |
| | | * æ¯æ¬¡å建Sessionæ¶è§¦å |
| | | */ |
| | | @Override |
| | | public void doCreateSession(String id) { |
| | | } |
| | | |
| | | /** |
| | | * æ¯æ¬¡æ³¨éSessionæ¶è§¦å |
| | | */ |
| | | @Override |
| | | public void doLogoutSession(String id) { |
| | | } |
| | | |
| | | /** |
| | | * æ¯æ¬¡Tokenç»ææ¶è§¦å |
| | | */ |
| | | @Override |
| | | public void doRenewTimeout(String loginType, Object loginId, String tokenValue, long timeout) { |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.web.service; |
| | | |
| | | |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.dromara.system.domain.SysClient; |
| | | import org.dromara.system.domain.vo.SysClientVo; |
| | | import org.dromara.web.domain.vo.LoginVo; |
| | | |
| | | /** |
| | | * ææçç¥ |
| | | * |
| | | * @author Michelle.Chung |
| | | */ |
| | | public interface IAuthStrategy { |
| | | |
| | | String BASE_NAME = "AuthStrategy"; |
| | | |
| | | /** |
| | | * ç»å½ |
| | | * |
| | | * @param body ç»å½å¯¹è±¡ |
| | | * @param client ææç®¡çè§å¾å¯¹è±¡ |
| | | * @param grantType ææç±»å |
| | | * @return ç»å½éªè¯ä¿¡æ¯ |
| | | */ |
| | | static LoginVo login(String body, SysClientVo client, String grantType) { |
| | | // ææç±»åå客æ·ç«¯id |
| | | String beanName = grantType + BASE_NAME; |
| | | if (!SpringUtils.containsBean(beanName)) { |
| | | throw new ServiceException("ææç±»å䏿£ç¡®!"); |
| | | } |
| | | IAuthStrategy instance = SpringUtils.getBean(beanName); |
| | | return instance.login(body, client); |
| | | } |
| | | |
| | | /** |
| | | * ç»å½ |
| | | * |
| | | * @param body ç»å½å¯¹è±¡ |
| | | * @param client ææç®¡çè§å¾å¯¹è±¡ |
| | | * @return ç»å½éªè¯ä¿¡æ¯ |
| | | */ |
| | | LoginVo login(String body, SysClientVo client); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.web.service; |
| | | |
| | | import cn.dev33.satoken.exception.NotLoginException; |
| | | import cn.dev33.satoken.stp.StpUtil; |
| | | import cn.hutool.core.bean.BeanUtil; |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.lang.Opt; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.baomidou.lock.annotation.Lock4j; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import me.zhyd.oauth.model.AuthUser; |
| | | import org.dromara.common.core.constant.CacheConstants; |
| | | import org.dromara.common.core.constant.Constants; |
| | | import org.dromara.common.core.constant.SystemConstants; |
| | | import org.dromara.common.core.constant.TenantConstants; |
| | | import org.dromara.common.core.domain.dto.PostDTO; |
| | | import org.dromara.common.core.domain.dto.RoleDTO; |
| | | import org.dromara.common.core.domain.model.LoginUser; |
| | | import org.dromara.common.core.enums.LoginType; |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | import org.dromara.common.core.exception.user.UserException; |
| | | import org.dromara.common.core.utils.*; |
| | | import org.dromara.common.log.event.LogininforEvent; |
| | | import org.dromara.common.mybatis.helper.DataPermissionHelper; |
| | | import org.dromara.common.redis.utils.RedisUtils; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | import org.dromara.common.tenant.exception.TenantException; |
| | | import org.dromara.common.tenant.helper.TenantHelper; |
| | | import org.dromara.system.domain.SysUser; |
| | | import org.dromara.system.domain.bo.SysSocialBo; |
| | | import org.dromara.system.domain.vo.*; |
| | | import org.dromara.system.mapper.SysUserMapper; |
| | | import org.dromara.system.service.*; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.time.Duration; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.function.Supplier; |
| | | |
| | | /** |
| | | * ç»å½æ ¡éªæ¹æ³ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @Slf4j |
| | | @Service |
| | | public class SysLoginService { |
| | | |
| | | @Value("${user.password.maxRetryCount}") |
| | | private Integer maxRetryCount; |
| | | |
| | | @Value("${user.password.lockTime}") |
| | | private Integer lockTime; |
| | | |
| | | private final ISysTenantService tenantService; |
| | | private final ISysPermissionService permissionService; |
| | | private final ISysSocialService sysSocialService; |
| | | private final ISysRoleService roleService; |
| | | private final ISysDeptService deptService; |
| | | private final ISysPostService postService; |
| | | private final SysUserMapper userMapper; |
| | | |
| | | |
| | | /** |
| | | * ç»å®ç¬¬ä¸æ¹ç¨æ· |
| | | * |
| | | * @param authUserData ææååºå®ä½ |
| | | */ |
| | | @Lock4j |
| | | public void socialRegister(AuthUser authUserData) { |
| | | String authId = authUserData.getSource() + authUserData.getUuid(); |
| | | // ç¬¬ä¸æ¹ç¨æ·ä¿¡æ¯ |
| | | SysSocialBo bo = BeanUtil.toBean(authUserData, SysSocialBo.class); |
| | | BeanUtil.copyProperties(authUserData.getToken(), bo); |
| | | Long userId = LoginHelper.getUserId(); |
| | | bo.setUserId(userId); |
| | | bo.setAuthId(authId); |
| | | bo.setOpenId(authUserData.getUuid()); |
| | | bo.setUserName(authUserData.getUsername()); |
| | | bo.setNickName(authUserData.getNickname()); |
| | | List<SysSocialVo> checkList = sysSocialService.selectByAuthId(authId); |
| | | if (CollUtil.isNotEmpty(checkList)) { |
| | | throw new ServiceException("æ¤ä¸æ¹è´¦å·å·²ç»è¢«ç»å®!"); |
| | | } |
| | | // æ¥è¯¢æ¯å¦å·²ç»ç»å®ç¨æ· |
| | | SysSocialBo params = new SysSocialBo(); |
| | | params.setUserId(userId); |
| | | params.setSource(bo.getSource()); |
| | | List<SysSocialVo> list = sysSocialService.queryList(params); |
| | | if (CollUtil.isEmpty(list)) { |
| | | // 没æç»å®ç¨æ·, æ°å¢ç¨æ·ä¿¡æ¯ |
| | | sysSocialService.insertByBo(bo); |
| | | } else { |
| | | // æ´æ°ç¨æ·ä¿¡æ¯ |
| | | bo.setId(list.get(0).getId()); |
| | | sysSocialService.updateByBo(bo); |
| | | // 妿è¦ç»å®çå¹³å°è´¦å·å·²ç»è¢«ç»å®è¿äº æ¯å¦æå¼å¸¸èªè¡å³æ |
| | | // throw new ServiceException("æ¤å¹³å°è´¦å·å·²ç»è¢«ç»å®!"); |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * éåºç»å½ |
| | | */ |
| | | public void logout() { |
| | | try { |
| | | LoginUser loginUser = LoginHelper.getLoginUser(); |
| | | if (ObjectUtil.isNull(loginUser)) { |
| | | return; |
| | | } |
| | | if (TenantHelper.isEnable() && LoginHelper.isSuperAdmin()) { |
| | | // è¶
级管çå ç»åºæ¸
é¤å¨æç§æ· |
| | | TenantHelper.clearDynamic(); |
| | | } |
| | | recordLogininfor(loginUser.getTenantId(), loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success")); |
| | | } catch (NotLoginException ignored) { |
| | | } finally { |
| | | try { |
| | | StpUtil.logout(); |
| | | } catch (NotLoginException ignored) { |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è®°å½ç»å½ä¿¡æ¯ |
| | | * |
| | | * @param tenantId ç§æ·ID |
| | | * @param username ç¨æ·å |
| | | * @param status ç¶æ |
| | | * @param message æ¶æ¯å
容 |
| | | */ |
| | | public void recordLogininfor(String tenantId, String username, String status, String message) { |
| | | LogininforEvent logininforEvent = new LogininforEvent(); |
| | | logininforEvent.setTenantId(tenantId); |
| | | logininforEvent.setUsername(username); |
| | | logininforEvent.setStatus(status); |
| | | logininforEvent.setMessage(message); |
| | | logininforEvent.setRequest(ServletUtils.getRequest()); |
| | | SpringUtils.context().publishEvent(logininforEvent); |
| | | } |
| | | |
| | | /** |
| | | * æå»ºç»å½ç¨æ· |
| | | */ |
| | | public LoginUser buildLoginUser(SysUserVo user) { |
| | | LoginUser loginUser = new LoginUser(); |
| | | Long userId = user.getUserId(); |
| | | loginUser.setTenantId(user.getTenantId()); |
| | | loginUser.setUserId(userId); |
| | | loginUser.setDeptId(user.getDeptId()); |
| | | loginUser.setUsername(user.getUserName()); |
| | | loginUser.setNickname(user.getNickName()); |
| | | loginUser.setUserType(user.getUserType()); |
| | | loginUser.setMenuPermission(permissionService.getMenuPermission(userId)); |
| | | loginUser.setRolePermission(permissionService.getRolePermission(userId)); |
| | | if (ObjectUtil.isNotNull(user.getDeptId())) { |
| | | Opt<SysDeptVo> deptOpt = Opt.of(user.getDeptId()).map(deptService::selectDeptById); |
| | | loginUser.setDeptName(deptOpt.map(SysDeptVo::getDeptName).orElse(StringUtils.EMPTY)); |
| | | loginUser.setDeptCategory(deptOpt.map(SysDeptVo::getDeptCategory).orElse(StringUtils.EMPTY)); |
| | | } |
| | | List<SysRoleVo> roles = roleService.selectRolesByUserId(userId); |
| | | List<SysPostVo> posts = postService.selectPostsByUserId(userId); |
| | | loginUser.setRoles(BeanUtil.copyToList(roles, RoleDTO.class)); |
| | | loginUser.setPosts(BeanUtil.copyToList(posts, PostDTO.class)); |
| | | return loginUser; |
| | | } |
| | | |
| | | /** |
| | | * è®°å½ç»å½ä¿¡æ¯ |
| | | * |
| | | * @param userId ç¨æ·ID |
| | | */ |
| | | public void recordLoginInfo(Long userId, String ip) { |
| | | SysUser sysUser = new SysUser(); |
| | | sysUser.setUserId(userId); |
| | | sysUser.setLoginIp(ip); |
| | | sysUser.setLoginDate(DateUtils.getNowDate()); |
| | | sysUser.setUpdateBy(userId); |
| | | DataPermissionHelper.ignore(() -> userMapper.updateById(sysUser)); |
| | | } |
| | | |
| | | /** |
| | | * ç»å½æ ¡éª |
| | | */ |
| | | public void checkLogin(LoginType loginType, String tenantId, String username, Supplier<Boolean> supplier) { |
| | | String errorKey = CacheConstants.PWD_ERR_CNT_KEY + username; |
| | | String loginFail = Constants.LOGIN_FAIL; |
| | | |
| | | // è·åç¨æ·ç»å½é误次æ°ï¼é»è®¤ä¸º0 (å¯èªå®ä¹éå¶çç¥ ä¾å¦: key + username + ip) |
| | | int errorNumber = ObjectUtil.defaultIfNull(RedisUtils.getCacheObject(errorKey), 0); |
| | | // é宿¶é´å
ç»å½ åè¸¢åº |
| | | if (errorNumber >= maxRetryCount) { |
| | | recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime)); |
| | | throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime); |
| | | } |
| | | |
| | | if (supplier.get()) { |
| | | // é误次æ°éå¢ |
| | | errorNumber++; |
| | | RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime)); |
| | | // è¾¾å°è§å®éè¯¯æ¬¡æ° åéå®ç»å½ |
| | | if (errorNumber >= maxRetryCount) { |
| | | recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime)); |
| | | throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime); |
| | | } else { |
| | | // æªè¾¾å°è§å®éè¯¯æ¬¡æ° |
| | | recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber)); |
| | | throw new UserException(loginType.getRetryLimitCount(), errorNumber); |
| | | } |
| | | } |
| | | |
| | | // ç»å½æå æ¸
空éè¯¯æ¬¡æ° |
| | | RedisUtils.deleteObject(errorKey); |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªç§æ· |
| | | * |
| | | * @param tenantId ç§æ·ID |
| | | */ |
| | | public void checkTenant(String tenantId) { |
| | | if (!TenantHelper.isEnable()) { |
| | | return; |
| | | } |
| | | if (StringUtils.isBlank(tenantId)) { |
| | | throw new TenantException("tenant.number.not.blank"); |
| | | } |
| | | if (TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) { |
| | | return; |
| | | } |
| | | SysTenantVo tenant = tenantService.queryByTenantId(tenantId); |
| | | if (ObjectUtil.isNull(tenant)) { |
| | | log.info("ç»å½ç§æ·ï¼{} ä¸åå¨.", tenantId); |
| | | throw new TenantException("tenant.not.exists"); |
| | | } else if (SystemConstants.DISABLE.equals(tenant.getStatus())) { |
| | | log.info("ç»å½ç§æ·ï¼{} 已被åç¨.", tenantId); |
| | | throw new TenantException("tenant.blocked"); |
| | | } else if (ObjectUtil.isNotNull(tenant.getExpireTime()) |
| | | && new Date().after(tenant.getExpireTime())) { |
| | | log.info("ç»å½ç§æ·ï¼{} å·²è¶
è¿æææ.", tenantId); |
| | | throw new TenantException("tenant.expired"); |
| | | } |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.web.service; |
| | | |
| | | import cn.hutool.crypto.digest.BCrypt; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.dromara.common.core.constant.Constants; |
| | | import org.dromara.common.core.constant.GlobalConstants; |
| | | import org.dromara.common.core.domain.model.RegisterBody; |
| | | import org.dromara.common.core.enums.UserType; |
| | | import org.dromara.common.core.exception.user.CaptchaException; |
| | | import org.dromara.common.core.exception.user.CaptchaExpireException; |
| | | import org.dromara.common.core.exception.user.UserException; |
| | | import org.dromara.common.core.utils.MessageUtils; |
| | | import org.dromara.common.core.utils.ServletUtils; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.log.event.LogininforEvent; |
| | | import org.dromara.common.redis.utils.RedisUtils; |
| | | import org.dromara.common.tenant.helper.TenantHelper; |
| | | import org.dromara.common.web.config.properties.CaptchaProperties; |
| | | import org.dromara.system.domain.SysUser; |
| | | import org.dromara.system.domain.bo.SysUserBo; |
| | | import org.dromara.system.mapper.SysUserMapper; |
| | | import org.dromara.system.service.ISysUserService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | /** |
| | | * æ³¨åæ ¡éªæ¹æ³ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @Service |
| | | public class SysRegisterService { |
| | | |
| | | private final ISysUserService userService; |
| | | private final SysUserMapper userMapper; |
| | | private final CaptchaProperties captchaProperties; |
| | | |
| | | /** |
| | | * 注å |
| | | */ |
| | | public void register(RegisterBody registerBody) { |
| | | String tenantId = registerBody.getTenantId(); |
| | | String username = registerBody.getUsername(); |
| | | String password = registerBody.getPassword(); |
| | | // æ ¡éªç¨æ·ç±»åæ¯å¦åå¨ |
| | | String userType = UserType.getUserType(registerBody.getUserType()).getUserType(); |
| | | |
| | | boolean captchaEnabled = captchaProperties.getEnable(); |
| | | // éªè¯ç å¼å
³ |
| | | if (captchaEnabled) { |
| | | validateCaptcha(tenantId, username, registerBody.getCode(), registerBody.getUuid()); |
| | | } |
| | | SysUserBo sysUser = new SysUserBo(); |
| | | sysUser.setUserName(username); |
| | | sysUser.setNickName(username); |
| | | sysUser.setPassword(BCrypt.hashpw(password)); |
| | | sysUser.setUserType(userType); |
| | | |
| | | boolean exist = TenantHelper.dynamic(tenantId, () -> { |
| | | return userMapper.exists(new LambdaQueryWrapper<SysUser>() |
| | | .eq(SysUser::getUserName, sysUser.getUserName())); |
| | | }); |
| | | if (exist) { |
| | | throw new UserException("user.register.save.error", username); |
| | | } |
| | | boolean regFlag = userService.registerUser(sysUser, tenantId); |
| | | if (!regFlag) { |
| | | throw new UserException("user.register.error"); |
| | | } |
| | | recordLogininfor(tenantId, username, Constants.REGISTER, MessageUtils.message("user.register.success")); |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªéªè¯ç |
| | | * |
| | | * @param username ç¨æ·å |
| | | * @param code éªè¯ç |
| | | * @param uuid å¯ä¸æ è¯ |
| | | */ |
| | | public void validateCaptcha(String tenantId, String username, String code, String uuid) { |
| | | String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + StringUtils.blankToDefault(uuid, ""); |
| | | String captcha = RedisUtils.getCacheObject(verifyKey); |
| | | RedisUtils.deleteObject(verifyKey); |
| | | if (captcha == null) { |
| | | recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")); |
| | | throw new CaptchaExpireException(); |
| | | } |
| | | if (!StringUtils.equalsIgnoreCase(code, captcha)) { |
| | | recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")); |
| | | throw new CaptchaException(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è®°å½ç»å½ä¿¡æ¯ |
| | | * |
| | | * @param tenantId ç§æ·ID |
| | | * @param username ç¨æ·å |
| | | * @param status ç¶æ |
| | | * @param message æ¶æ¯å
容 |
| | | * @return |
| | | */ |
| | | private void recordLogininfor(String tenantId, String username, String status, String message) { |
| | | LogininforEvent logininforEvent = new LogininforEvent(); |
| | | logininforEvent.setTenantId(tenantId); |
| | | logininforEvent.setUsername(username); |
| | | logininforEvent.setStatus(status); |
| | | logininforEvent.setMessage(message); |
| | | logininforEvent.setRequest(ServletUtils.getRequest()); |
| | | SpringUtils.context().publishEvent(logininforEvent); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.web.service.impl; |
| | | |
| | | import cn.dev33.satoken.stp.StpUtil; |
| | | import cn.dev33.satoken.stp.parameter.SaLoginParameter; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.core.constant.Constants; |
| | | import org.dromara.common.core.constant.GlobalConstants; |
| | | import org.dromara.common.core.constant.SystemConstants; |
| | | import org.dromara.common.core.domain.model.EmailLoginBody; |
| | | import org.dromara.common.core.domain.model.LoginUser; |
| | | import org.dromara.common.core.enums.LoginType; |
| | | import org.dromara.common.core.exception.user.CaptchaExpireException; |
| | | import org.dromara.common.core.exception.user.UserException; |
| | | import org.dromara.common.core.utils.MessageUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.core.utils.ValidatorUtils; |
| | | import org.dromara.common.json.utils.JsonUtils; |
| | | import org.dromara.common.redis.utils.RedisUtils; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | import org.dromara.common.tenant.helper.TenantHelper; |
| | | import org.dromara.system.domain.SysUser; |
| | | import org.dromara.system.domain.vo.SysClientVo; |
| | | import org.dromara.system.domain.vo.SysUserVo; |
| | | import org.dromara.system.mapper.SysUserMapper; |
| | | import org.dromara.web.domain.vo.LoginVo; |
| | | import org.dromara.web.service.IAuthStrategy; |
| | | import org.dromara.web.service.SysLoginService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | /** |
| | | * é®ä»¶è®¤è¯çç¥ |
| | | * |
| | | * @author Michelle.Chung |
| | | */ |
| | | @Slf4j |
| | | @Service("email" + IAuthStrategy.BASE_NAME) |
| | | @RequiredArgsConstructor |
| | | public class EmailAuthStrategy implements IAuthStrategy { |
| | | |
| | | private final SysLoginService loginService; |
| | | private final SysUserMapper userMapper; |
| | | |
| | | @Override |
| | | public LoginVo login(String body, SysClientVo client) { |
| | | EmailLoginBody loginBody = JsonUtils.parseObject(body, EmailLoginBody.class); |
| | | ValidatorUtils.validate(loginBody); |
| | | String tenantId = loginBody.getTenantId(); |
| | | String email = loginBody.getEmail(); |
| | | String emailCode = loginBody.getEmailCode(); |
| | | LoginUser loginUser = TenantHelper.dynamic(tenantId, () -> { |
| | | SysUserVo user = loadUserByEmail(email); |
| | | loginService.checkLogin(LoginType.EMAIL, tenantId, user.getUserName(), () -> !validateEmailCode(tenantId, email, emailCode)); |
| | | // æ¤å¤å¯æ ¹æ®ç»å½ç¨æ·çæ°æ®ä¸å èªè¡å建 loginUser 屿§ä¸å¤ç¨ç»§æ¿æ©å±å°±è¡äº |
| | | return loginService.buildLoginUser(user); |
| | | }); |
| | | loginUser.setClientKey(client.getClientKey()); |
| | | loginUser.setDeviceType(client.getDeviceType()); |
| | | SaLoginParameter model = new SaLoginParameter(); |
| | | model.setDeviceType(client.getDeviceType()); |
| | | // èªå®ä¹åé
ä¸åç¨æ·ä½ç³» ä¸å token æææ¶é´ ä¸è®¾ç½®é»è®¤èµ°å
¨å± yml é
ç½® |
| | | // ä¾å¦: åå°ç¨æ·30åéè¿æ appç¨æ·1å¤©è¿æ |
| | | model.setTimeout(client.getTimeout()); |
| | | model.setActiveTimeout(client.getActiveTimeout()); |
| | | model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId()); |
| | | // çætoken |
| | | LoginHelper.login(loginUser, model); |
| | | |
| | | LoginVo loginVo = new LoginVo(); |
| | | loginVo.setAccessToken(StpUtil.getTokenValue()); |
| | | loginVo.setExpireIn(StpUtil.getTokenTimeout()); |
| | | loginVo.setClientId(client.getClientId()); |
| | | return loginVo; |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªé®ç®±éªè¯ç |
| | | */ |
| | | private boolean validateEmailCode(String tenantId, String email, String emailCode) { |
| | | String code = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + email); |
| | | if (StringUtils.isBlank(code)) { |
| | | loginService.recordLogininfor(tenantId, email, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")); |
| | | throw new CaptchaExpireException(); |
| | | } |
| | | return code.equals(emailCode); |
| | | } |
| | | |
| | | private SysUserVo loadUserByEmail(String email) { |
| | | SysUserVo user = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getEmail, email)); |
| | | if (ObjectUtil.isNull(user)) { |
| | | log.info("ç»å½ç¨æ·ï¼{} ä¸åå¨.", email); |
| | | throw new UserException("user.not.exists", email); |
| | | } else if (SystemConstants.DISABLE.equals(user.getStatus())) { |
| | | log.info("ç»å½ç¨æ·ï¼{} 已被åç¨.", email); |
| | | throw new UserException("user.blocked", email); |
| | | } |
| | | return user; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.web.service.impl; |
| | | |
| | | import cn.dev33.satoken.stp.StpUtil; |
| | | import cn.dev33.satoken.stp.parameter.SaLoginParameter; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import cn.hutool.crypto.digest.BCrypt; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.core.constant.Constants; |
| | | import org.dromara.common.core.constant.GlobalConstants; |
| | | import org.dromara.common.core.constant.SystemConstants; |
| | | import org.dromara.common.core.domain.model.LoginUser; |
| | | import org.dromara.common.core.domain.model.PasswordLoginBody; |
| | | import org.dromara.common.core.enums.LoginType; |
| | | import org.dromara.common.core.exception.user.CaptchaException; |
| | | import org.dromara.common.core.exception.user.CaptchaExpireException; |
| | | import org.dromara.common.core.exception.user.UserException; |
| | | import org.dromara.common.core.utils.MessageUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.core.utils.ValidatorUtils; |
| | | import org.dromara.common.json.utils.JsonUtils; |
| | | import org.dromara.common.redis.utils.RedisUtils; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | import org.dromara.common.tenant.helper.TenantHelper; |
| | | import org.dromara.common.web.config.properties.CaptchaProperties; |
| | | import org.dromara.system.domain.SysUser; |
| | | import org.dromara.system.domain.vo.SysClientVo; |
| | | import org.dromara.system.domain.vo.SysUserVo; |
| | | import org.dromara.system.mapper.SysUserMapper; |
| | | import org.dromara.web.domain.vo.LoginVo; |
| | | import org.dromara.web.service.IAuthStrategy; |
| | | import org.dromara.web.service.SysLoginService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | /** |
| | | * å¯ç 认è¯çç¥ |
| | | * |
| | | * @author Michelle.Chung |
| | | */ |
| | | @Slf4j |
| | | @Service("password" + IAuthStrategy.BASE_NAME) |
| | | @RequiredArgsConstructor |
| | | public class PasswordAuthStrategy implements IAuthStrategy { |
| | | |
| | | private final CaptchaProperties captchaProperties; |
| | | private final SysLoginService loginService; |
| | | private final SysUserMapper userMapper; |
| | | |
| | | @Override |
| | | public LoginVo login(String body, SysClientVo client) { |
| | | PasswordLoginBody loginBody = JsonUtils.parseObject(body, PasswordLoginBody.class); |
| | | ValidatorUtils.validate(loginBody); |
| | | String tenantId = loginBody.getTenantId(); |
| | | String username = loginBody.getUsername(); |
| | | String password = loginBody.getPassword(); |
| | | String code = loginBody.getCode(); |
| | | String uuid = loginBody.getUuid(); |
| | | |
| | | boolean captchaEnabled = captchaProperties.getEnable(); |
| | | // éªè¯ç å¼å
³ |
| | | if (captchaEnabled) { |
| | | validateCaptcha(tenantId, username, code, uuid); |
| | | } |
| | | LoginUser loginUser = TenantHelper.dynamic(tenantId, () -> { |
| | | SysUserVo user = loadUserByUsername(username); |
| | | loginService.checkLogin(LoginType.PASSWORD, tenantId, username, () -> !BCrypt.checkpw(password, user.getPassword())); |
| | | // æ¤å¤å¯æ ¹æ®ç»å½ç¨æ·çæ°æ®ä¸å èªè¡å建 loginUser |
| | | return loginService.buildLoginUser(user); |
| | | }); |
| | | loginUser.setClientKey(client.getClientKey()); |
| | | loginUser.setDeviceType(client.getDeviceType()); |
| | | SaLoginParameter model = new SaLoginParameter(); |
| | | model.setDeviceType(client.getDeviceType()); |
| | | // èªå®ä¹åé
ä¸åç¨æ·ä½ç³» ä¸å token æææ¶é´ ä¸è®¾ç½®é»è®¤èµ°å
¨å± yml é
ç½® |
| | | // ä¾å¦: åå°ç¨æ·30åéè¿æ appç¨æ·1å¤©è¿æ |
| | | model.setTimeout(client.getTimeout()); |
| | | model.setActiveTimeout(client.getActiveTimeout()); |
| | | model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId()); |
| | | // çætoken |
| | | LoginHelper.login(loginUser, model); |
| | | |
| | | LoginVo loginVo = new LoginVo(); |
| | | loginVo.setAccessToken(StpUtil.getTokenValue()); |
| | | loginVo.setExpireIn(StpUtil.getTokenTimeout()); |
| | | loginVo.setClientId(client.getClientId()); |
| | | return loginVo; |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªéªè¯ç |
| | | * |
| | | * @param username ç¨æ·å |
| | | * @param code éªè¯ç |
| | | * @param uuid å¯ä¸æ è¯ |
| | | */ |
| | | private void validateCaptcha(String tenantId, String username, String code, String uuid) { |
| | | String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + StringUtils.blankToDefault(uuid, ""); |
| | | String captcha = RedisUtils.getCacheObject(verifyKey); |
| | | RedisUtils.deleteObject(verifyKey); |
| | | if (captcha == null) { |
| | | loginService.recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")); |
| | | throw new CaptchaExpireException(); |
| | | } |
| | | if (!StringUtils.equalsIgnoreCase(code, captcha)) { |
| | | loginService.recordLogininfor(tenantId, username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")); |
| | | throw new CaptchaException(); |
| | | } |
| | | } |
| | | |
| | | private SysUserVo loadUserByUsername(String username) { |
| | | SysUserVo user = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserName, username)); |
| | | if (ObjectUtil.isNull(user)) { |
| | | log.info("ç»å½ç¨æ·ï¼{} ä¸åå¨.", username); |
| | | throw new UserException("user.not.exists", username); |
| | | } else if (SystemConstants.DISABLE.equals(user.getStatus())) { |
| | | log.info("ç»å½ç¨æ·ï¼{} 已被åç¨.", username); |
| | | throw new UserException("user.blocked", username); |
| | | } |
| | | return user; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.web.service.impl; |
| | | |
| | | import cn.dev33.satoken.stp.StpUtil; |
| | | import cn.dev33.satoken.stp.parameter.SaLoginParameter; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.core.constant.Constants; |
| | | import org.dromara.common.core.constant.GlobalConstants; |
| | | import org.dromara.common.core.constant.SystemConstants; |
| | | import org.dromara.common.core.domain.model.LoginUser; |
| | | import org.dromara.common.core.domain.model.SmsLoginBody; |
| | | import org.dromara.common.core.enums.LoginType; |
| | | import org.dromara.common.core.exception.user.CaptchaExpireException; |
| | | import org.dromara.common.core.exception.user.UserException; |
| | | import org.dromara.common.core.utils.MessageUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.core.utils.ValidatorUtils; |
| | | import org.dromara.common.json.utils.JsonUtils; |
| | | import org.dromara.common.redis.utils.RedisUtils; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | import org.dromara.common.tenant.helper.TenantHelper; |
| | | import org.dromara.system.domain.SysUser; |
| | | import org.dromara.system.domain.vo.SysClientVo; |
| | | import org.dromara.system.domain.vo.SysUserVo; |
| | | import org.dromara.system.mapper.SysUserMapper; |
| | | import org.dromara.web.domain.vo.LoginVo; |
| | | import org.dromara.web.service.IAuthStrategy; |
| | | import org.dromara.web.service.SysLoginService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | /** |
| | | * ç信认è¯çç¥ |
| | | * |
| | | * @author Michelle.Chung |
| | | */ |
| | | @Slf4j |
| | | @Service("sms" + IAuthStrategy.BASE_NAME) |
| | | @RequiredArgsConstructor |
| | | public class SmsAuthStrategy implements IAuthStrategy { |
| | | |
| | | private final SysLoginService loginService; |
| | | private final SysUserMapper userMapper; |
| | | |
| | | @Override |
| | | public LoginVo login(String body, SysClientVo client) { |
| | | SmsLoginBody loginBody = JsonUtils.parseObject(body, SmsLoginBody.class); |
| | | ValidatorUtils.validate(loginBody); |
| | | String tenantId = loginBody.getTenantId(); |
| | | String phonenumber = loginBody.getPhonenumber(); |
| | | String smsCode = loginBody.getSmsCode(); |
| | | LoginUser loginUser = TenantHelper.dynamic(tenantId, () -> { |
| | | SysUserVo user = loadUserByPhonenumber(phonenumber); |
| | | loginService.checkLogin(LoginType.SMS, tenantId, user.getUserName(), () -> !validateSmsCode(tenantId, phonenumber, smsCode)); |
| | | // æ¤å¤å¯æ ¹æ®ç»å½ç¨æ·çæ°æ®ä¸å èªè¡å建 loginUser 屿§ä¸å¤ç¨ç»§æ¿æ©å±å°±è¡äº |
| | | return loginService.buildLoginUser(user); |
| | | }); |
| | | loginUser.setClientKey(client.getClientKey()); |
| | | loginUser.setDeviceType(client.getDeviceType()); |
| | | SaLoginParameter model = new SaLoginParameter(); |
| | | model.setDeviceType(client.getDeviceType()); |
| | | // èªå®ä¹åé
ä¸åç¨æ·ä½ç³» ä¸å token æææ¶é´ ä¸è®¾ç½®é»è®¤èµ°å
¨å± yml é
ç½® |
| | | // ä¾å¦: åå°ç¨æ·30åéè¿æ appç¨æ·1å¤©è¿æ |
| | | model.setTimeout(client.getTimeout()); |
| | | model.setActiveTimeout(client.getActiveTimeout()); |
| | | model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId()); |
| | | // çætoken |
| | | LoginHelper.login(loginUser, model); |
| | | |
| | | LoginVo loginVo = new LoginVo(); |
| | | loginVo.setAccessToken(StpUtil.getTokenValue()); |
| | | loginVo.setExpireIn(StpUtil.getTokenTimeout()); |
| | | loginVo.setClientId(client.getClientId()); |
| | | return loginVo; |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªçä¿¡éªè¯ç |
| | | */ |
| | | private boolean validateSmsCode(String tenantId, String phonenumber, String smsCode) { |
| | | String code = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + phonenumber); |
| | | if (StringUtils.isBlank(code)) { |
| | | loginService.recordLogininfor(tenantId, phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")); |
| | | throw new CaptchaExpireException(); |
| | | } |
| | | return code.equals(smsCode); |
| | | } |
| | | |
| | | private SysUserVo loadUserByPhonenumber(String phonenumber) { |
| | | SysUserVo user = userMapper.selectVoOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getPhonenumber, phonenumber)); |
| | | if (ObjectUtil.isNull(user)) { |
| | | log.info("ç»å½ç¨æ·ï¼{} ä¸åå¨.", phonenumber); |
| | | throw new UserException("user.not.exists", phonenumber); |
| | | } else if (SystemConstants.DISABLE.equals(user.getStatus())) { |
| | | log.info("ç»å½ç¨æ·ï¼{} 已被åç¨.", phonenumber); |
| | | throw new UserException("user.blocked", phonenumber); |
| | | } |
| | | return user; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.web.service.impl; |
| | | |
| | | import cn.dev33.satoken.stp.StpUtil; |
| | | import cn.dev33.satoken.stp.parameter.SaLoginParameter; |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import me.zhyd.oauth.model.AuthResponse; |
| | | import me.zhyd.oauth.model.AuthUser; |
| | | import org.dromara.common.core.constant.SystemConstants; |
| | | import org.dromara.common.core.domain.model.LoginUser; |
| | | import org.dromara.common.core.domain.model.SocialLoginBody; |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | import org.dromara.common.core.exception.user.UserException; |
| | | import org.dromara.common.core.utils.StreamUtils; |
| | | import org.dromara.common.core.utils.ValidatorUtils; |
| | | import org.dromara.common.json.utils.JsonUtils; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | import org.dromara.common.social.config.properties.SocialProperties; |
| | | import org.dromara.common.social.utils.SocialUtils; |
| | | import org.dromara.common.tenant.helper.TenantHelper; |
| | | import org.dromara.system.domain.vo.SysClientVo; |
| | | import org.dromara.system.domain.vo.SysSocialVo; |
| | | import org.dromara.system.domain.vo.SysUserVo; |
| | | import org.dromara.system.mapper.SysUserMapper; |
| | | import org.dromara.system.service.ISysSocialService; |
| | | import org.dromara.web.domain.vo.LoginVo; |
| | | import org.dromara.web.service.IAuthStrategy; |
| | | import org.dromara.web.service.SysLoginService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.List; |
| | | import java.util.Optional; |
| | | |
| | | /** |
| | | * ç¬¬ä¸æ¹ææçç¥ |
| | | * |
| | | * @author thiszhc is ä¸ä¸ |
| | | */ |
| | | @Slf4j |
| | | @Service("social" + IAuthStrategy.BASE_NAME) |
| | | @RequiredArgsConstructor |
| | | public class SocialAuthStrategy implements IAuthStrategy { |
| | | |
| | | private final SocialProperties socialProperties; |
| | | private final ISysSocialService sysSocialService; |
| | | private final SysUserMapper userMapper; |
| | | private final SysLoginService loginService; |
| | | |
| | | /** |
| | | * ç»å½-ç¬¬ä¸æ¹ææç»å½ |
| | | * |
| | | * @param body ç»å½ä¿¡æ¯ |
| | | * @param client 客æ·ç«¯ä¿¡æ¯ |
| | | */ |
| | | @Override |
| | | public LoginVo login(String body, SysClientVo client) { |
| | | SocialLoginBody loginBody = JsonUtils.parseObject(body, SocialLoginBody.class); |
| | | ValidatorUtils.validate(loginBody); |
| | | AuthResponse<AuthUser> response = SocialUtils.loginAuth( |
| | | loginBody.getSource(), loginBody.getSocialCode(), |
| | | loginBody.getSocialState(), socialProperties); |
| | | if (!response.ok()) { |
| | | throw new ServiceException(response.getMsg()); |
| | | } |
| | | AuthUser authUserData = response.getData(); |
| | | |
| | | List<SysSocialVo> list = sysSocialService.selectByAuthId(authUserData.getSource() + authUserData.getUuid()); |
| | | if (CollUtil.isEmpty(list)) { |
| | | throw new ServiceException("ä½ è¿æ²¡æç»å®ç¬¬ä¸æ¹è´¦å·ï¼ç»å®åæå¯ä»¥ç»å½ï¼"); |
| | | } |
| | | SysSocialVo social; |
| | | if (TenantHelper.isEnable()) { |
| | | Optional<SysSocialVo> opt = StreamUtils.findAny(list, x -> x.getTenantId().equals(loginBody.getTenantId())); |
| | | if (opt.isEmpty()) { |
| | | throw new ServiceException("对ä¸èµ·ï¼ä½ 没ææéç»å½å½åç§æ·ï¼"); |
| | | } |
| | | social = opt.get(); |
| | | } else { |
| | | social = list.get(0); |
| | | } |
| | | LoginUser loginUser = TenantHelper.dynamic(social.getTenantId(), () -> { |
| | | SysUserVo user = loadUser(social.getUserId()); |
| | | // æ¤å¤å¯æ ¹æ®ç»å½ç¨æ·çæ°æ®ä¸å èªè¡å建 loginUser 屿§ä¸å¤ç¨ç»§æ¿æ©å±å°±è¡äº |
| | | return loginService.buildLoginUser(user); |
| | | }); |
| | | loginUser.setClientKey(client.getClientKey()); |
| | | loginUser.setDeviceType(client.getDeviceType()); |
| | | SaLoginParameter model = new SaLoginParameter(); |
| | | model.setDeviceType(client.getDeviceType()); |
| | | // èªå®ä¹åé
ä¸åç¨æ·ä½ç³» ä¸å token æææ¶é´ ä¸è®¾ç½®é»è®¤èµ°å
¨å± yml é
ç½® |
| | | // ä¾å¦: åå°ç¨æ·30åéè¿æ appç¨æ·1å¤©è¿æ |
| | | model.setTimeout(client.getTimeout()); |
| | | model.setActiveTimeout(client.getActiveTimeout()); |
| | | model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId()); |
| | | // çætoken |
| | | LoginHelper.login(loginUser, model); |
| | | |
| | | LoginVo loginVo = new LoginVo(); |
| | | loginVo.setAccessToken(StpUtil.getTokenValue()); |
| | | loginVo.setExpireIn(StpUtil.getTokenTimeout()); |
| | | loginVo.setClientId(client.getClientId()); |
| | | return loginVo; |
| | | } |
| | | |
| | | private SysUserVo loadUser(Long userId) { |
| | | SysUserVo user = userMapper.selectVoById(userId); |
| | | if (ObjectUtil.isNull(user)) { |
| | | log.info("ç»å½ç¨æ·ï¼{} ä¸åå¨.", ""); |
| | | throw new UserException("user.not.exists", ""); |
| | | } else if (SystemConstants.DISABLE.equals(user.getStatus())) { |
| | | log.info("ç»å½ç¨æ·ï¼{} 已被åç¨.", ""); |
| | | throw new UserException("user.blocked", ""); |
| | | } |
| | | return user; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.web.service.impl; |
| | | |
| | | import cn.dev33.satoken.stp.StpUtil; |
| | | import cn.dev33.satoken.stp.parameter.SaLoginParameter; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import me.zhyd.oauth.config.AuthConfig; |
| | | import me.zhyd.oauth.model.AuthCallback; |
| | | import me.zhyd.oauth.model.AuthResponse; |
| | | import me.zhyd.oauth.model.AuthToken; |
| | | import me.zhyd.oauth.model.AuthUser; |
| | | import me.zhyd.oauth.request.AuthRequest; |
| | | import me.zhyd.oauth.request.AuthWechatMiniProgramRequest; |
| | | import org.dromara.common.core.constant.SystemConstants; |
| | | import org.dromara.common.core.domain.model.XcxLoginBody; |
| | | import org.dromara.common.core.domain.model.XcxLoginUser; |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | import org.dromara.common.core.utils.ValidatorUtils; |
| | | import org.dromara.common.json.utils.JsonUtils; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | import org.dromara.system.domain.vo.SysClientVo; |
| | | import org.dromara.system.domain.vo.SysUserVo; |
| | | import org.dromara.web.domain.vo.LoginVo; |
| | | import org.dromara.web.service.IAuthStrategy; |
| | | import org.dromara.web.service.SysLoginService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | /** |
| | | * å°ç¨åºè®¤è¯çç¥ |
| | | * |
| | | * @author Michelle.Chung |
| | | */ |
| | | @Slf4j |
| | | @Service("xcx" + IAuthStrategy.BASE_NAME) |
| | | @RequiredArgsConstructor |
| | | public class XcxAuthStrategy implements IAuthStrategy { |
| | | |
| | | private final SysLoginService loginService; |
| | | |
| | | @Override |
| | | public LoginVo login(String body, SysClientVo client) { |
| | | XcxLoginBody loginBody = JsonUtils.parseObject(body, XcxLoginBody.class); |
| | | ValidatorUtils.validate(loginBody); |
| | | // xcxCode 为 å°ç¨åºè°ç¨ wx.login ææåè·å |
| | | String xcxCode = loginBody.getXcxCode(); |
| | | // å¤ä¸ªå°ç¨åºè¯å«ä½¿ç¨ |
| | | String appid = loginBody.getAppid(); |
| | | |
| | | // æ ¡éª appid + appsrcret + xcxCode è°ç¨ç»å½åè¯æ ¡éªæ¥å£ è·å session_key ä¸ openid |
| | | AuthRequest authRequest = new AuthWechatMiniProgramRequest(AuthConfig.builder() |
| | | .clientId(appid).clientSecret("èªè¡å¡«åå¯é¥ 坿 ¹æ®ä¸åappidå¡«å
¥ä¸åå¯é¥") |
| | | .ignoreCheckRedirectUri(true).ignoreCheckState(true).build()); |
| | | AuthCallback authCallback = new AuthCallback(); |
| | | authCallback.setCode(xcxCode); |
| | | AuthResponse<AuthUser> resp = authRequest.login(authCallback); |
| | | String openid, unionId; |
| | | if (resp.ok()) { |
| | | AuthToken token = resp.getData().getToken(); |
| | | openid = token.getOpenId(); |
| | | // 微信å°ç¨åºåªæå
³èå°å¾®ä¿¡å¼æ¾å¹³å°ä¸ä¹åæè½è·åå° unionIdï¼å æ¤unionIdä¸ä¸å®è½è¿åã |
| | | unionId = token.getUnionId(); |
| | | } else { |
| | | throw new ServiceException(resp.getMsg()); |
| | | } |
| | | // æ¡æ¶ç»å½ä¸éå¶ä»ä»ä¹è¡¨æ¥è¯¢ åªè¦æç»æå»ºåº LoginUser å³å¯ |
| | | SysUserVo user = loadUserByOpenid(openid); |
| | | // æ¤å¤å¯æ ¹æ®ç»å½ç¨æ·çæ°æ®ä¸å èªè¡å建 loginUser 屿§ä¸å¤ç¨ç»§æ¿æ©å±å°±è¡äº |
| | | XcxLoginUser loginUser = new XcxLoginUser(); |
| | | loginUser.setTenantId(user.getTenantId()); |
| | | loginUser.setUserId(user.getUserId()); |
| | | loginUser.setUsername(user.getUserName()); |
| | | loginUser.setNickname(user.getNickName()); |
| | | loginUser.setUserType(user.getUserType()); |
| | | loginUser.setClientKey(client.getClientKey()); |
| | | loginUser.setDeviceType(client.getDeviceType()); |
| | | loginUser.setOpenid(openid); |
| | | |
| | | SaLoginParameter model = new SaLoginParameter(); |
| | | model.setDeviceType(client.getDeviceType()); |
| | | // èªå®ä¹åé
ä¸åç¨æ·ä½ç³» ä¸å token æææ¶é´ ä¸è®¾ç½®é»è®¤èµ°å
¨å± yml é
ç½® |
| | | // ä¾å¦: åå°ç¨æ·30åéè¿æ appç¨æ·1å¤©è¿æ |
| | | model.setTimeout(client.getTimeout()); |
| | | model.setActiveTimeout(client.getActiveTimeout()); |
| | | model.setExtra(LoginHelper.CLIENT_KEY, client.getClientId()); |
| | | // çætoken |
| | | LoginHelper.login(loginUser, model); |
| | | |
| | | LoginVo loginVo = new LoginVo(); |
| | | loginVo.setAccessToken(StpUtil.getTokenValue()); |
| | | loginVo.setExpireIn(StpUtil.getTokenTimeout()); |
| | | loginVo.setClientId(client.getClientId()); |
| | | loginVo.setOpenid(openid); |
| | | return loginVo; |
| | | } |
| | | |
| | | private SysUserVo loadUserByOpenid(String openid) { |
| | | // ä½¿ç¨ openid æ¥è¯¢ç»å®ç¨æ· 妿ªç»å®ç¨æ· åæ ¹æ®ä¸å¡èªè¡å¤ç ä¾å¦ å建é»è®¤ç¨æ· |
| | | // todo èªè¡å®ç° userService.selectUserByOpenid(openid); |
| | | SysUserVo user = new SysUserVo(); |
| | | if (ObjectUtil.isNull(user)) { |
| | | log.info("ç»å½ç¨æ·ï¼{} ä¸åå¨.", openid); |
| | | // todo ç¨æ·ä¸åå¨ ä¸å¡é»è¾èªè¡å®ç° |
| | | } else if (SystemConstants.DISABLE.equals(user.getStatus())) { |
| | | log.info("ç»å½ç¨æ·ï¼{} 已被åç¨.", openid); |
| | | // todo ç¨æ·å·²è¢«åç¨ ä¸å¡é»è¾èªè¡å®ç° |
| | | } |
| | | return user; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | --- # çæ§ä¸å¿é
ç½® |
| | | spring.boot.admin.client: |
| | | # å¢å 客æ·ç«¯å¼å
³ |
| | | enabled: false |
| | | url: http://localhost:9090/admin |
| | | instance: |
| | | service-host-type: IP |
| | | metadata: |
| | | username: ${spring.boot.admin.client.username} |
| | | userpassword: ${spring.boot.admin.client.password} |
| | | username: @monitor.username@ |
| | | password: @monitor.password@ |
| | | |
| | | --- # snail-job é
ç½® |
| | | snail-job: |
| | | enabled: false |
| | | # éè¦å¨ SnailJob åå°ç»ç®¡çå建对åºåç§°çç»,ç¶åå建任å¡çæ¶å鿩坹åºçç»,æè½æ£ç¡®åæ´¾ä»»å¡ |
| | | group: "ruoyi_group" |
| | | # SnailJob æ¥å
¥éªè¯ä»¤ç è¯¦è§ script/sql/ry_job.sql `sj_group_config` 表 |
| | | token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT" |
| | | server: |
| | | host: 127.0.0.1 |
| | | port: 17888 |
| | | # å½å空é´UUID è¯¦è§ script/sql/ry_job.sql `sj_namespace`表`unique_id`åæ®µ |
| | | namespace: ${spring.profiles.active} |
| | | # é主åºç¨ç«¯å£æ¼ç§» |
| | | port: 2${server.port} |
| | | # 客æ·ç«¯ipæå® |
| | | host: |
| | | |
| | | --- # æ°æ®æºé
ç½® |
| | | spring: |
| | | datasource: |
| | | type: com.zaxxer.hikari.HikariDataSource |
| | | # å¨ææ°æ®æºææ¡£ https://www.kancloud.cn/tracy5546/dynamic-datasource/content |
| | | dynamic: |
| | | # æ§è½åææä»¶(ææ§è½æè ä¸å»ºè®®ç产ç¯å¢ä½¿ç¨) |
| | | p6spy: true |
| | | # 设置é»è®¤çæ°æ®æºæè
æ°æ®æºç»,é»è®¤å¼å³ä¸º master |
| | | primary: master |
| | | # ä¸¥æ ¼æ¨¡å¼ å¹é
ä¸å°æ°æ®æºåæ¥é |
| | | strict: true |
| | | datasource: |
| | | # ä¸»åºæ°æ®æº |
| | | master: |
| | | type: ${spring.datasource.type} |
| | | driverClassName: org.postgresql.Driver |
| | | url: jdbc:postgresql://192.168.2.26:5432/postgres?currentSchema=public&serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true |
| | | username: postgres |
| | | password: 123456 |
| | | # master: |
| | | # type: ${spring.datasource.type} |
| | | # driverClassName: com.mysql.cj.jdbc.Driver |
| | | # # jdbc ææåæ°é
ç½®åè https://lionli.blog.csdn.net/article/details/122018562 |
| | | # # rewriteBatchedStatements=true æ¹å¤çä¼å 大å¹
æåæ¹éæå
¥æ´æ°å 餿§è½(å¯¹æ°æ®åºææ§è½æè ä½¿ç¨æ¹éæä½åºèèæ§è½é®é¢) |
| | | # url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true |
| | | # username: root |
| | | # password: 123456 |
| | | # # ä»åºæ°æ®æº |
| | | # slave: |
| | | # lazy: true |
| | | # type: ${spring.datasource.type} |
| | | # driverClassName: com.mysql.cj.jdbc.Driver |
| | | # url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true |
| | | # username: |
| | | # password: |
| | | # oracle: |
| | | # type: ${spring.datasource.type} |
| | | # driverClassName: oracle.jdbc.OracleDriver |
| | | # url: jdbc:oracle:thin:@//localhost:1521/XE |
| | | # username: ROOT |
| | | # password: root |
| | | # postgres: |
| | | # type: ${spring.datasource.type} |
| | | # driverClassName: org.postgresql.Driver |
| | | # url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true |
| | | # username: root |
| | | # password: root |
| | | # sqlserver: |
| | | # type: ${spring.datasource.type} |
| | | # driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver |
| | | # url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true |
| | | # username: SA |
| | | # password: root |
| | | hikari: |
| | | # æå¤§è¿æ¥æ± æ°é |
| | | maxPoolSize: 20 |
| | | # æå°ç©ºé²çº¿ç¨æ°é |
| | | minIdle: 10 |
| | | # é
ç½®è·åè¿æ¥çå¾
è¶
æ¶çæ¶é´ |
| | | connectionTimeout: 30000 |
| | | # æ ¡éªè¶
æ¶æ¶é´ |
| | | validationTimeout: 5000 |
| | | # 空é²è¿æ¥åæ´»æå¤§æ¶é´ï¼é»è®¤10åé |
| | | idleTimeout: 600000 |
| | | # æ¤å±æ§æ§å¶æ± ä¸è¿æ¥çæé¿çå½å¨æï¼å¼0表示æ éçå½å¨æï¼é»è®¤30åé |
| | | maxLifetime: 1800000 |
| | | # å¤ä¹
æ£æ¥ä¸æ¬¡è¿æ¥çæ´»æ§ |
| | | keepaliveTime: 30000 |
| | | |
| | | --- # redis åæºé
ç½®(åæºä¸é群åªè½å¼å¯ä¸ä¸ªå¦ä¸ä¸ªéè¦æ³¨éæ) |
| | | spring.data: |
| | | redis: |
| | | # å°å |
| | | host: localhost |
| | | # 端å£ï¼é»è®¤ä¸º6677 |
| | | port: 6379 |
| | | # æ°æ®åºç´¢å¼ |
| | | database: 0 |
| | | # redis å¯ç å¿
é¡»é
ç½® |
| | | # password: |
| | | # è¿æ¥è¶
æ¶æ¶é´ |
| | | timeout: 10s |
| | | # æ¯å¦å¼å¯ssl |
| | | ssl.enabled: false |
| | | |
| | | # redisson é
ç½® |
| | | redisson: |
| | | # redis keyåç¼ |
| | | keyPrefix: |
| | | # çº¿ç¨æ± æ°é |
| | | threads: 4 |
| | | # Nettyçº¿ç¨æ± æ°é |
| | | nettyThreads: 8 |
| | | # åèç¹é
ç½® |
| | | singleServerConfig: |
| | | # 客æ·ç«¯åç§° ä¸è½ç¨ä¸æ |
| | | clientName: RuoYi-Vue-Plus |
| | | # æå°ç©ºé²è¿æ¥æ° |
| | | connectionMinimumIdleSize: 8 |
| | | # è¿æ¥æ± å¤§å° |
| | | connectionPoolSize: 32 |
| | | # è¿æ¥ç©ºé²è¶
æ¶ï¼åä½ï¼æ¯«ç§ |
| | | idleConnectionTimeout: 10000 |
| | | # å½ä»¤çå¾
è¶
æ¶ï¼åä½ï¼æ¯«ç§ |
| | | timeout: 3000 |
| | | # åå¸å订é
è¿æ¥æ± å¤§å° |
| | | subscriptionConnectionPoolSize: 50 |
| | | |
| | | --- # mail é®ä»¶åé |
| | | mail: |
| | | enabled: false |
| | | host: smtp.163.com |
| | | port: 465 |
| | | # æ¯å¦éè¦ç¨æ·åå¯ç éªè¯ |
| | | auth: true |
| | | # åéæ¹ï¼éµå¾ªRFC-822æ å |
| | | from: xxx@163.com |
| | | # ç¨æ·åï¼æ³¨æï¼å¦æä½¿ç¨foxmailé®ç®±ï¼æ¤å¤user为qqå·ï¼ |
| | | user: xxx@163.com |
| | | # å¯ç ï¼æ³¨æï¼æäºé®ç®±éè¦ä¸ºSMTPæå¡åç¬è®¾ç½®å¯ç ï¼è¯¦æ
æ¥çç¸å
³å¸®å©ï¼ |
| | | pass: xxxxxxxxxx |
| | | # ä½¿ç¨ STARTTLSå®å
¨è¿æ¥ï¼STARTTLSæ¯å¯¹çº¯ææ¬éä¿¡åè®®çæ©å±ã |
| | | starttlsEnable: true |
| | | # 使ç¨SSLå®å
¨è¿æ¥ |
| | | sslEnable: true |
| | | # SMTPè¶
æ¶æ¶é¿ï¼å使¯«ç§ï¼ç¼ºçå¼ä¸è¶
æ¶ |
| | | timeout: 0 |
| | | # Socketè¿æ¥è¶
æ¶å¼ï¼å使¯«ç§ï¼ç¼ºçå¼ä¸è¶
æ¶ |
| | | connectionTimeout: 0 |
| | | |
| | | --- # sms çä¿¡ æ¯æ é¿éäº è
¾è®¯äº äºç ççåå¼åæ ·ççä¿¡æå¡å |
| | | # https://sms4j.com/doc3/ å·®å¼é
ç½®ææ¡£å°å æ¯æåååå¤é
ç½®ï¼å¯ä»¥é
ç½®å¤ä¸ªåæ¶ä½¿ç¨ |
| | | sms: |
| | | # é
ç½®æºç±»åç¨äºæ å®é
ç½®æ¥æº(interface,yaml) |
| | | config-type: yaml |
| | | # ç¨äºæ å®ymlä¸çé
ç½®æ¯å¦å¼å¯çä¿¡æ¦æªï¼æ¥å£é
ç½®ä¸åæ¤éå¶ |
| | | restricted: true |
| | | # çä¿¡æ¦æªéå¶åææºå·æ¯åéæå¤§åéï¼åªå¯¹å¼å¯äºæ¦æªçé
ç½®ææ |
| | | minute-max: 1 |
| | | # çä¿¡æ¦æªéå¶åææºå·æ¯æ¥æå¤§åééï¼åªå¯¹å¼å¯äºæ¦æªçé
ç½®ææ |
| | | account-max: 30 |
| | | # 以ä¸é
ç½®æ¥èªäº org.dromara.sms4j.provider.config.BaseConfigç±»ä¸ |
| | | blends: |
| | | # å¯ä¸ID ç¨äºåéç信寻æ¾å
·ä½é
ç½® é便å®ä¹å«ç¨ä¸æå³å¯ |
| | | # å¯ä»¥åæ¶åå¨ä¸¤ä¸ªç¸ååå ä¾å¦: ali1 ali2 两个ä¸åçé¿éçä¿¡è´¦å· ä¹å¯ç¨äºåºåç§æ· |
| | | config1: |
| | | # æ¡æ¶å®ä¹çåååç§°æ è¯ï¼æ 宿¤é
ç½®æ¯åªä¸ªååï¼è¯¦ç»è¯·çååæ è¯ä»ç»é¨å |
| | | supplier: alibaba |
| | | # æäºç§°ä¸ºaccessKeyæäºç§°ä¹ä¸ºapiKeyï¼ä¹æç§°ä¸ºsdkKeyæè
appIdã |
| | | access-key-id: æ¨çaccessKey |
| | | # 称为accessSecretæäºç§°ä¹ä¸ºapiSecret |
| | | access-key-secret: æ¨çaccessKeySecret |
| | | signature: æ¨ççä¿¡ç¾å |
| | | sdk-app-id: æ¨çsdkAppId |
| | | config2: |
| | | # ååæ è¯ï¼æ 宿¤é
ç½®æ¯åªä¸ªååï¼è¯¦ç»è¯·çååæ è¯ä»ç»é¨å |
| | | supplier: tencent |
| | | access-key-id: æ¨çaccessKey |
| | | access-key-secret: æ¨çaccessKeySecret |
| | | signature: æ¨ççä¿¡ç¾å |
| | | sdk-app-id: æ¨çsdkAppId |
| | | |
| | | |
| | | --- # 䏿¹ææ |
| | | justauth: |
| | | # å端å¤ç½è®¿é®å°å |
| | | address: http://localhost:80 |
| | | type: |
| | | maxkey: |
| | | # maxkey æå¡å¨å°å |
| | | # 注æ å¦ä¸åé
ç½®åä¸éè¦ä¿®æ¹ maxkey å·²ç»å
ç½®å¥½äºæ°æ® |
| | | server-url: http://sso.maxkey.top |
| | | client-id: 876892492581044224 |
| | | client-secret: x1Y5MTMwNzIwMjMxNTM4NDc3Mzche8 |
| | | redirect-uri: ${justauth.address}/social-callback?source=maxkey |
| | | topiam: |
| | | # topiam æå¡å¨å°å |
| | | server-url: http://127.0.0.1:1898/api/v1/authorize/y0q************spq***********8ol |
| | | client-id: 449c4*********937************759 |
| | | client-secret: ac7***********1e0************28d |
| | | redirect-uri: ${justauth.address}/social-callback?source=topiam |
| | | scopes: [openid, email, phone, profile] |
| | | qq: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=qq |
| | | union-id: false |
| | | weibo: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=weibo |
| | | gitee: |
| | | client-id: 91436b7940090d09c72c7daf85b959cfd5f215d67eea73acbf61b6b590751a98 |
| | | client-secret: 02c6fcfd70342980cd8dd2f2c06c1a350645d76c754d7a264c4e125f9ba915ac |
| | | redirect-uri: ${justauth.address}/social-callback?source=gitee |
| | | dingtalk: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=dingtalk |
| | | baidu: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=baidu |
| | | csdn: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=csdn |
| | | coding: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=coding |
| | | coding-group-name: xx |
| | | oschina: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=oschina |
| | | alipay_wallet: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=alipay_wallet |
| | | alipay-public-key: MIIB**************DAQAB |
| | | wechat_open: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=wechat_open |
| | | wechat_mp: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=wechat_mp |
| | | wechat_enterprise: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=wechat_enterprise |
| | | agent-id: 1000002 |
| | | gitlab: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=gitlab |
| | | gitea: |
| | | # å端æ¹å¨ https://gitee.com/JavaLionLi/plus-ui/pulls/204 |
| | | # gitea æå¡å¨å°å |
| | | server-url: https://demo.gitea.com |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=gitea |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | --- # ä¸´æ¶æä»¶åå¨ä½ç½® é¿å
ä¸´æ¶æä»¶è¢«ç³»ç»æ¸
çæ¥é |
| | | spring.servlet.multipart.location: /ruoyi/server/temp |
| | | |
| | | --- # çæ§ä¸å¿é
ç½® |
| | | spring.boot.admin.client: |
| | | # å¢å 客æ·ç«¯å¼å
³ |
| | | enabled: true |
| | | url: http://localhost:9090/admin |
| | | instance: |
| | | service-host-type: IP |
| | | metadata: |
| | | username: ${spring.boot.admin.client.username} |
| | | userpassword: ${spring.boot.admin.client.password} |
| | | username: @monitor.username@ |
| | | password: @monitor.password@ |
| | | |
| | | --- # snail-job é
ç½® |
| | | snail-job: |
| | | enabled: true |
| | | # éè¦å¨ SnailJob åå°ç»ç®¡çå建对åºåç§°çç»,ç¶åå建任å¡çæ¶å鿩坹åºçç»,æè½æ£ç¡®åæ´¾ä»»å¡ |
| | | group: "ruoyi_group" |
| | | # SnailJob æ¥å
¥éªè¯ä»¤ç è¯¦è§ script/sql/ry_job.sql `sj_group_config`表 |
| | | token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT" |
| | | server: |
| | | host: 127.0.0.1 |
| | | port: 17888 |
| | | # å½å空é´UUID è¯¦è§ script/sql/ry_job.sql `sj_namespace`表`unique_id`åæ®µ |
| | | namespace: ${spring.profiles.active} |
| | | # é主åºç¨ç«¯å£æ¼ç§» |
| | | port: 2${server.port} |
| | | # 客æ·ç«¯ipæå® |
| | | host: |
| | | |
| | | --- # æ°æ®æºé
ç½® |
| | | spring: |
| | | datasource: |
| | | type: com.zaxxer.hikari.HikariDataSource |
| | | # å¨ææ°æ®æºææ¡£ https://www.kancloud.cn/tracy5546/dynamic-datasource/content |
| | | dynamic: |
| | | # æ§è½åææä»¶(ææ§è½æè ä¸å»ºè®®ç产ç¯å¢ä½¿ç¨) |
| | | p6spy: false |
| | | # 设置é»è®¤çæ°æ®æºæè
æ°æ®æºç»,é»è®¤å¼å³ä¸º master |
| | | primary: master |
| | | # ä¸¥æ ¼æ¨¡å¼ å¹é
ä¸å°æ°æ®æºåæ¥é |
| | | strict: true |
| | | datasource: |
| | | # ä¸»åºæ°æ®æº |
| | | master: |
| | | type: ${spring.datasource.type} |
| | | driverClassName: com.mysql.cj.jdbc.Driver |
| | | # jdbc ææåæ°é
ç½®åè https://lionli.blog.csdn.net/article/details/122018562 |
| | | # rewriteBatchedStatements=true æ¹å¤çä¼å 大å¹
æåæ¹éæå
¥æ´æ°å 餿§è½(å¯¹æ°æ®åºææ§è½æè ä½¿ç¨æ¹éæä½åºèèæ§è½é®é¢) |
| | | url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true |
| | | username: root |
| | | password: root |
| | | # # ä»åºæ°æ®æº |
| | | # slave: |
| | | # lazy: true |
| | | # type: ${spring.datasource.type} |
| | | # driverClassName: com.mysql.cj.jdbc.Driver |
| | | # url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true |
| | | # username: |
| | | # password: |
| | | # oracle: |
| | | # type: ${spring.datasource.type} |
| | | # driverClassName: oracle.jdbc.OracleDriver |
| | | # url: jdbc:oracle:thin:@//localhost:1521/XE |
| | | # username: ROOT |
| | | # password: root |
| | | # postgres: |
| | | # type: ${spring.datasource.type} |
| | | # driverClassName: org.postgresql.Driver |
| | | # url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true |
| | | # username: root |
| | | # password: root |
| | | # sqlserver: |
| | | # type: ${spring.datasource.type} |
| | | # driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver |
| | | # url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true |
| | | # username: SA |
| | | # password: root |
| | | hikari: |
| | | # æå¤§è¿æ¥æ± æ°é |
| | | maxPoolSize: 20 |
| | | # æå°ç©ºé²çº¿ç¨æ°é |
| | | minIdle: 10 |
| | | # é
ç½®è·åè¿æ¥çå¾
è¶
æ¶çæ¶é´ |
| | | connectionTimeout: 30000 |
| | | # æ ¡éªè¶
æ¶æ¶é´ |
| | | validationTimeout: 5000 |
| | | # 空é²è¿æ¥åæ´»æå¤§æ¶é´ï¼é»è®¤10åé |
| | | idleTimeout: 600000 |
| | | # æ¤å±æ§æ§å¶æ± ä¸è¿æ¥çæé¿çå½å¨æï¼å¼0表示æ éçå½å¨æï¼é»è®¤30åé |
| | | maxLifetime: 1800000 |
| | | # å¤ä¹
æ£æ¥ä¸æ¬¡è¿æ¥çæ´»æ§ |
| | | keepaliveTime: 30000 |
| | | |
| | | --- # redis åæºé
ç½®(åæºä¸é群åªè½å¼å¯ä¸ä¸ªå¦ä¸ä¸ªéè¦æ³¨éæ) |
| | | spring.data: |
| | | redis: |
| | | # å°å |
| | | host: localhost |
| | | # 端å£ï¼é»è®¤ä¸º6379 |
| | | port: 6379 |
| | | # æ°æ®åºç´¢å¼ |
| | | database: 0 |
| | | # redis å¯ç å¿
é¡»é
ç½® |
| | | password: ruoyi123 |
| | | # è¿æ¥è¶
æ¶æ¶é´ |
| | | timeout: 10s |
| | | # æ¯å¦å¼å¯ssl |
| | | ssl.enabled: false |
| | | |
| | | # redisson é
ç½® |
| | | redisson: |
| | | # redis keyåç¼ |
| | | keyPrefix: |
| | | # çº¿ç¨æ± æ°é |
| | | threads: 16 |
| | | # Nettyçº¿ç¨æ± æ°é |
| | | nettyThreads: 32 |
| | | # åèç¹é
ç½® |
| | | singleServerConfig: |
| | | # 客æ·ç«¯åç§° ä¸è½ç¨ä¸æ |
| | | clientName: RuoYi-Vue-Plus |
| | | # æå°ç©ºé²è¿æ¥æ° |
| | | connectionMinimumIdleSize: 32 |
| | | # è¿æ¥æ± å¤§å° |
| | | connectionPoolSize: 64 |
| | | # è¿æ¥ç©ºé²è¶
æ¶ï¼åä½ï¼æ¯«ç§ |
| | | idleConnectionTimeout: 10000 |
| | | # å½ä»¤çå¾
è¶
æ¶ï¼åä½ï¼æ¯«ç§ |
| | | timeout: 3000 |
| | | # åå¸å订é
è¿æ¥æ± å¤§å° |
| | | subscriptionConnectionPoolSize: 50 |
| | | |
| | | --- # mail é®ä»¶åé |
| | | mail: |
| | | enabled: false |
| | | host: smtp.163.com |
| | | port: 465 |
| | | # æ¯å¦éè¦ç¨æ·åå¯ç éªè¯ |
| | | auth: true |
| | | # åéæ¹ï¼éµå¾ªRFC-822æ å |
| | | from: xxx@163.com |
| | | # ç¨æ·åï¼æ³¨æï¼å¦æä½¿ç¨foxmailé®ç®±ï¼æ¤å¤user为qqå·ï¼ |
| | | user: xxx@163.com |
| | | # å¯ç ï¼æ³¨æï¼æäºé®ç®±éè¦ä¸ºSMTPæå¡åç¬è®¾ç½®å¯ç ï¼è¯¦æ
æ¥çç¸å
³å¸®å©ï¼ |
| | | pass: xxxxxxxxxx |
| | | # ä½¿ç¨ STARTTLSå®å
¨è¿æ¥ï¼STARTTLSæ¯å¯¹çº¯ææ¬éä¿¡åè®®çæ©å±ã |
| | | starttlsEnable: true |
| | | # 使ç¨SSLå®å
¨è¿æ¥ |
| | | sslEnable: true |
| | | # SMTPè¶
æ¶æ¶é¿ï¼å使¯«ç§ï¼ç¼ºçå¼ä¸è¶
æ¶ |
| | | timeout: 0 |
| | | # Socketè¿æ¥è¶
æ¶å¼ï¼å使¯«ç§ï¼ç¼ºçå¼ä¸è¶
æ¶ |
| | | connectionTimeout: 0 |
| | | |
| | | --- # sms çä¿¡ æ¯æ é¿éäº è
¾è®¯äº äºç ççåå¼åæ ·ççä¿¡æå¡å |
| | | # https://sms4j.com/doc3/ å·®å¼é
ç½®ææ¡£å°å æ¯æåååå¤é
ç½®ï¼å¯ä»¥é
ç½®å¤ä¸ªåæ¶ä½¿ç¨ |
| | | sms: |
| | | # é
ç½®æºç±»åç¨äºæ å®é
ç½®æ¥æº(interface,yaml) |
| | | config-type: yaml |
| | | # ç¨äºæ å®ymlä¸çé
ç½®æ¯å¦å¼å¯çä¿¡æ¦æªï¼æ¥å£é
ç½®ä¸åæ¤éå¶ |
| | | restricted: true |
| | | # çä¿¡æ¦æªéå¶åææºå·æ¯åéæå¤§åéï¼åªå¯¹å¼å¯äºæ¦æªçé
ç½®ææ |
| | | minute-max: 1 |
| | | # çä¿¡æ¦æªéå¶åææºå·æ¯æ¥æå¤§åééï¼åªå¯¹å¼å¯äºæ¦æªçé
ç½®ææ |
| | | account-max: 30 |
| | | # 以ä¸é
ç½®æ¥èªäº org.dromara.sms4j.provider.config.BaseConfigç±»ä¸ |
| | | blends: |
| | | # å¯ä¸ID ç¨äºåéç信寻æ¾å
·ä½é
ç½® é便å®ä¹å«ç¨ä¸æå³å¯ |
| | | # å¯ä»¥åæ¶åå¨ä¸¤ä¸ªç¸ååå ä¾å¦: ali1 ali2 两个ä¸åçé¿éçä¿¡è´¦å· ä¹å¯ç¨äºåºåç§æ· |
| | | config1: |
| | | # æ¡æ¶å®ä¹çåååç§°æ è¯ï¼æ 宿¤é
ç½®æ¯åªä¸ªååï¼è¯¦ç»è¯·çååæ è¯ä»ç»é¨å |
| | | supplier: alibaba |
| | | # æäºç§°ä¸ºaccessKeyæäºç§°ä¹ä¸ºapiKeyï¼ä¹æç§°ä¸ºsdkKeyæè
appIdã |
| | | access-key-id: æ¨çaccessKey |
| | | # 称为accessSecretæäºç§°ä¹ä¸ºapiSecret |
| | | access-key-secret: æ¨çaccessKeySecret |
| | | signature: æ¨ççä¿¡ç¾å |
| | | sdk-app-id: æ¨çsdkAppId |
| | | config2: |
| | | # ååæ è¯ï¼æ 宿¤é
ç½®æ¯åªä¸ªååï¼è¯¦ç»è¯·çååæ è¯ä»ç»é¨å |
| | | supplier: tencent |
| | | access-key-id: æ¨çaccessKey |
| | | access-key-secret: æ¨çaccessKeySecret |
| | | signature: æ¨ççä¿¡ç¾å |
| | | sdk-app-id: æ¨çsdkAppId |
| | | |
| | | --- # 䏿¹ææ |
| | | justauth: |
| | | # å端å¤ç½è®¿é®å°å |
| | | address: http://localhost:80 |
| | | type: |
| | | maxkey: |
| | | # maxkey æå¡å¨å°å |
| | | # 注æ å¦ä¸åé
ç½®åä¸éè¦ä¿®æ¹ maxkey å·²ç»å
ç½®å¥½äºæ°æ® |
| | | server-url: http://sso.maxkey.top |
| | | client-id: 876892492581044224 |
| | | client-secret: x1Y5MTMwNzIwMjMxNTM4NDc3Mzche8 |
| | | redirect-uri: ${justauth.address}/social-callback?source=maxkey |
| | | topiam: |
| | | # topiam æå¡å¨å°å |
| | | server-url: http://127.0.0.1:1989/api/v1/authorize/y0q************spq***********8ol |
| | | client-id: 449c4*********937************759 |
| | | client-secret: ac7***********1e0************28d |
| | | redirect-uri: ${justauth.address}/social-callback?source=topiam |
| | | scopes: [ openid, email, phone, profile ] |
| | | qq: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=qq |
| | | union-id: false |
| | | weibo: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=weibo |
| | | gitee: |
| | | client-id: 91436b7940090d09c72c7daf85b959cfd5f215d67eea73acbf61b6b590751a98 |
| | | client-secret: 02c6fcfd70342980cd8dd2f2c06c1a350645d76c754d7a264c4e125f9ba915ac |
| | | redirect-uri: ${justauth.address}/social-callback?source=gitee |
| | | dingtalk: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=dingtalk |
| | | baidu: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=baidu |
| | | csdn: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=csdn |
| | | coding: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=coding |
| | | coding-group-name: xx |
| | | oschina: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=oschina |
| | | alipay_wallet: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=alipay_wallet |
| | | alipay-public-key: MIIB**************DAQAB |
| | | wechat_open: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=wechat_open |
| | | wechat_mp: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=wechat_mp |
| | | wechat_enterprise: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=wechat_enterprise |
| | | agent-id: 1000002 |
| | | gitlab: |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=gitlab |
| | | gitea: |
| | | # å端æ¹å¨ https://gitee.com/JavaLionLi/plus-ui/pulls/204 |
| | | # gitea æå¡å¨å°å |
| | | server-url: https://demo.gitea.com |
| | | client-id: 10**********6 |
| | | client-secret: 1f7d08**********5b7**********29e |
| | | redirect-uri: ${justauth.address}/social-callback?source=gitea |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # å¼åç¯å¢é
ç½® |
| | | server: |
| | | # æå¡å¨çHTTP端å£ï¼é»è®¤ä¸º8080 |
| | | port: 8080 |
| | | servlet: |
| | | # åºç¨ç访é®è·¯å¾ |
| | | context-path: / |
| | | # undertow é
ç½® |
| | | undertow: |
| | | # HTTP postå
容çæå¤§å¤§å°ãå½å¼ä¸º-1æ¶ï¼é»è®¤å¼ä¸ºå¤§å°æ¯æ éç |
| | | max-http-post-size: -1 |
| | | # 以ä¸çé
ç½®ä¼å½±åbuffer,è¿äºbufferä¼ç¨äºæå¡å¨è¿æ¥çIOæä½,æç¹ç±»ä¼¼nettyçæ± åå
å管ç |
| | | # æ¯åbufferç空é´å¤§å°,è¶å°ç空é´è¢«å©ç¨è¶å
å |
| | | buffer-size: 512 |
| | | # æ¯å¦åé
çç´æ¥å
å |
| | | direct-buffers: true |
| | | threads: |
| | | # 设置IOçº¿ç¨æ°, å®ä¸»è¦æ§è¡éé»å¡çä»»å¡,å®ä»¬ä¼è´è´£å¤ä¸ªè¿æ¥, é»è®¤è®¾ç½®æ¯ä¸ªCPUæ ¸å¿ä¸ä¸ªçº¿ç¨ |
| | | io: 8 |
| | | # é»å¡ä»»å¡çº¿ç¨æ± , 彿§è¡ç±»ä¼¼servlet请æ±é»å¡æä½, undertowä¼ä»è¿ä¸ªçº¿ç¨æ± ä¸åå¾çº¿ç¨,å®çå¼è®¾ç½®åå³äºç³»ç»çè´è½½ |
| | | worker: 256 |
| | | |
| | | captcha: |
| | | # æ¯å¦å¯ç¨éªè¯ç æ ¡éª |
| | | enable: false |
| | | # éªè¯ç ç±»å math æ°ç»è®¡ç® char å符éªè¯ |
| | | type: math |
| | | # æ°åéªè¯ç 使° |
| | | numberLength: 1 |
| | | # å符éªè¯ç é¿åº¦ |
| | | charLength: 4 |
| | | |
| | | # æ¥å¿é
ç½® |
| | | logging: |
| | | level: |
| | | org.dromara: @logging.level@ |
| | | org.springframework: warn |
| | | org.mybatis.spring.mapper: error |
| | | org.apache.fury: warn |
| | | config: classpath:logback-plus.xml |
| | | |
| | | # ç¨æ·é
ç½® |
| | | user: |
| | | password: |
| | | # å¯ç æå¤§éè¯¯æ¬¡æ° |
| | | maxRetryCount: 5 |
| | | # å¯ç é宿¶é´ï¼é»è®¤10åéï¼ |
| | | lockTime: 10 |
| | | |
| | | # Springé
ç½® |
| | | spring: |
| | | application: |
| | | name: RuoYi-Vue-Plus |
| | | threads: |
| | | # å¼å¯èæçº¿ç¨ ä»
jdk21å¯ç¨ |
| | | virtual: |
| | | enabled: false |
| | | task: |
| | | execution: |
| | | # ä» springboot 3.5 å¼å§ springèªå¸¦çº¿ç¨æ± |
| | | # ä¸åéè¦ AsyncConfigä¸ThreadPoolConfig å¯ç´æ¥æ³¨å
¥çº¿ç¨æ± ä½¿ç¨ |
| | | thread-name-prefix: async- |
| | | # ç±springèªå·±åå§åçº¿ç¨æ± |
| | | mode: force |
| | | # èµæºä¿¡æ¯ |
| | | messages: |
| | | # å½é
åèµæºæä»¶è·¯å¾ |
| | | basename: i18n/messages |
| | | profiles: |
| | | active: @profiles.active@ |
| | | # æä»¶ä¸ä¼ |
| | | servlet: |
| | | multipart: |
| | | # å个æä»¶å¤§å° |
| | | max-file-size: 10MB |
| | | # 设置æ»ä¸ä¼ çæä»¶å¤§å° |
| | | max-request-size: 20MB |
| | | mvc: |
| | | # 设置éæèµæºè·¯å¾ 鲿¢ææè¯·æ±é½å»æ¥éæèµæº |
| | | static-path-pattern: /static/** |
| | | format: |
| | | date-time: yyyy-MM-dd HH:mm:ss |
| | | jackson: |
| | | # æ¥ææ ¼å¼å |
| | | date-format: yyyy-MM-dd HH:mm:ss |
| | | serialization: |
| | | # æ ¼å¼åè¾åº |
| | | indent_output: false |
| | | # å¿½ç¥æ æ³è½¬æ¢ç对象 |
| | | fail_on_empty_beans: false |
| | | deserialization: |
| | | # å
许对象忽ç¥jsonä¸ä¸åå¨ç屿§ |
| | | fail_on_unknown_properties: false |
| | | |
| | | # Sa-Tokené
ç½® |
| | | sa-token: |
| | | # tokenåç§° (忶乿¯cookieåç§°) |
| | | token-name: Authorization |
| | | # æ¯å¦å
许åä¸è´¦å·å¹¶åç»å½ (为trueæ¶å
许ä¸èµ·ç»å½, 为falseæ¶æ°ç»å½æ¤ææ§ç»å½) |
| | | is-concurrent: true |
| | | # å¨å¤äººç»å½åä¸è´¦å·æ¶ï¼æ¯å¦å
±ç¨ä¸ä¸ªtoken (为trueæ¶ææç»å½å
±ç¨ä¸ä¸ªtoken, 为falseæ¶æ¯æ¬¡ç»å½æ°å»ºä¸ä¸ªtoken) |
| | | is-share: false |
| | | # jwtç§é¥ |
| | | jwt-secret-key: abcdefghijklmnopqrstuvwxyz |
| | | |
| | | # securityé
ç½® |
| | | security: |
| | | # æé¤è·¯å¾ |
| | | excludes: |
| | | - /*.html |
| | | - /**/*.html |
| | | - /**/*.css |
| | | - /**/*.js |
| | | - /favicon.ico |
| | | - /error |
| | | - /*/api-docs |
| | | - /*/api-docs/** |
| | | - /warm-flow-ui/config |
| | | |
| | | # å¤ç§æ·é
ç½® |
| | | tenant: |
| | | # æ¯å¦å¼å¯ |
| | | enable: false |
| | | # æé¤è¡¨ |
| | | excludes: |
| | | - sys_menu |
| | | - sys_tenant |
| | | - sys_tenant_package |
| | | - sys_role_dept |
| | | - sys_role_menu |
| | | - sys_user_post |
| | | - sys_user_role |
| | | - sys_client |
| | | - sys_oss_config |
| | | - flow_spel |
| | | |
| | | # MyBatisPlusé
ç½® |
| | | # https://baomidou.com/config/ |
| | | mybatis-plus: |
| | | # èªå®ä¹é
ç½® æ¯å¦å
¨å±å¼å¯é»è¾å é¤ å
³éå ææé»è¾å é¤åè½å°å¤±æ |
| | | enableLogicDelete: true |
| | | # å¤å
åä½¿ç¨ ä¾å¦ org.dromara.**.mapper,org.xxx.**.mapper |
| | | mapperPackage: org.dromara.**.mapper |
| | | # 对åºç XML æä»¶ä½ç½® |
| | | mapperLocations: classpath*:mapper/**/*Mapper.xml |
| | | # å®ä½æ«æï¼å¤ä¸ªpackageç¨éå·æè
åå·åé |
| | | typeAliasesPackage: org.dromara.**.domain |
| | | global-config: |
| | | dbConfig: |
| | | # 主é®ç±»å |
| | | # AUTO èªå¢ NONE 空 INPUT ç¨æ·è¾å
¥ ASSIGN_ID éªè± ASSIGN_UUID å¯ä¸ UUID |
| | | # å¦éæ¹ä¸ºèªå¢ éè¦å°æ°æ®åºè¡¨å
¨é¨è®¾ç½®ä¸ºèªå¢ |
| | | idType: ASSIGN_ID |
| | | |
| | | # æ°æ®å å¯ |
| | | mybatis-encryptor: |
| | | # æ¯å¦å¼å¯å å¯ |
| | | enable: false |
| | | # é»è®¤å å¯ç®æ³ |
| | | algorithm: BASE64 |
| | | # ç¼ç æ¹å¼ BASE64/HEXãé»è®¤BASE64 |
| | | encode: BASE64 |
| | | # å®å
¨ç§é¥ å¯¹ç§°ç®æ³çç§é¥ å¦ï¼AESï¼SM4 |
| | | password: |
| | | # å
¬ç§é¥ éå¯¹ç§°ç®æ³çå
¬ç§é¥ å¦ï¼SM2ï¼RSA |
| | | publicKey: |
| | | privateKey: |
| | | |
| | | # apiæ¥å£å å¯ |
| | | api-decrypt: |
| | | # æ¯å¦å¼å¯å
¨å±æ¥å£å å¯ |
| | | enabled: false |
| | | # AES å å¯å¤´æ è¯ |
| | | headerFlag: encrypt-key |
| | | # ååºå å¯å
¬é¥ éå¯¹ç§°ç®æ³çå
¬ç§é¥ å¦ï¼SM2ï¼RSA 使ç¨è
请èªè¡æ´æ¢ |
| | | # 对åºå端解å¯ç§é¥ MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE= |
| | | publicKey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJnNwrj4hi/y3CCJu868ghCG5dUj8wZK++RNlTLcXoMmdZWEQ/u02RgD5LyLAXGjLOjbMtC+/J9qofpSGTKSx/MCAwEAAQ== |
| | | # 请æ±è§£å¯ç§é¥ éå¯¹ç§°ç®æ³çå
¬ç§é¥ å¦ï¼SM2ï¼RSA 使ç¨è
请èªè¡æ´æ¢ |
| | | # 对åºå端å å¯å
¬é¥ MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ== |
| | | privateKey: MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKNPuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gAkM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWowcSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99EcvDQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthhYhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3UP8iWi1Qw0Y= |
| | | |
| | | springdoc: |
| | | api-docs: |
| | | # æ¯å¦å¼å¯æ¥å£ææ¡£ |
| | | enabled: true |
| | | info: |
| | | # æ é¢ |
| | | title: 'æ é¢ï¼RuoYi-Vue-Pluså¤ç§æ·ç®¡çç³»ç»_æ¥å£ææ¡£' |
| | | # æè¿° |
| | | description: 'æè¿°ï¼ç¨äºç®¡çé墿ä¸å
¬å¸ç人åä¿¡æ¯,å
·ä½å
æ¬XXX,XXX模å...' |
| | | # çæ¬ |
| | | version: 'çæ¬å·: ${project.version}' |
| | | # ä½è
ä¿¡æ¯ |
| | | contact: |
| | | name: Lion Li |
| | | email: crazylionli@163.com |
| | | url: https://gitee.com/dromara/RuoYi-Vue-Plus |
| | | #è¿éå®ä¹äºä¸¤ä¸ªåç»ï¼å¯å®ä¹å¤ä¸ªï¼ä¹å¯ä»¥ä¸å®ä¹ |
| | | group-configs: |
| | | - group: 1.æ¼ç¤ºæ¨¡å |
| | | packages-to-scan: org.dromara.demo |
| | | - group: 2.éç¨æ¨¡å |
| | | packages-to-scan: org.dromara.web |
| | | - group: 3.ç³»ç»æ¨¡å |
| | | packages-to-scan: org.dromara.system |
| | | - group: 4.代ç çææ¨¡å |
| | | packages-to-scan: org.dromara.generator |
| | | - group: 5.工使µæ¨¡å |
| | | packages-to-scan: org.dromara.workflow |
| | | |
| | | # 鲿¢XSSæ»å» |
| | | xss: |
| | | # è¿æ»¤å¼å
³ |
| | | enabled: true |
| | | # æé¤é¾æ¥ |
| | | excludeUrls: |
| | | - /system/notice |
| | | |
| | | --- # åå¸å¼é lock4j å
¨å±é
ç½® |
| | | lock4j: |
| | | # è·ååå¸å¼éè¶
æ¶æ¶é´ï¼é»è®¤ä¸º 3000 æ¯«ç§ |
| | | acquire-timeout: 3000 |
| | | # åå¸å¼éçè¶
æ¶æ¶é´ï¼é»è®¤ä¸º 30 ç§ |
| | | expire: 30000 |
| | | |
| | | --- # Actuator çæ§ç«¯ç¹çé
置项 |
| | | management: |
| | | endpoints: |
| | | web: |
| | | exposure: |
| | | include: '*' |
| | | endpoint: |
| | | health: |
| | | show-details: ALWAYS |
| | | logfile: |
| | | external-file: ./logs/sys-console.log |
| | | |
| | | --- # é»è®¤/æ¨è使ç¨sseæ¨é |
| | | sse: |
| | | enabled: true |
| | | path: /resource/sse |
| | | |
| | | --- # websocket |
| | | websocket: |
| | | # 妿å
³é éè¦åå端å¼å
³ä¸èµ·å
³é |
| | | enabled: false |
| | | # è·¯å¾ |
| | | path: /resource/websocket |
| | | # è®¾ç½®è®¿é®æºå°å |
| | | allowedOrigins: '*' |
| | | |
| | | --- # warm-flow工使µé
ç½® |
| | | warm-flow: |
| | | # æ¯å¦å¼å¯å·¥ä½æµï¼é»è®¤true |
| | | enabled: false |
| | | # æ¯å¦å¼å¯è®¾è®¡å¨ui |
| | | ui: true |
| | | # æ¯å¦æ¾ç¤ºæµç¨å¾é¡¶é¨æå |
| | | top-text-show: true |
| | | # æ¯å¦æ¸²æèç¹æ¬æµ®æç¤ºï¼é»è®¤true |
| | | node-tooltip: true |
| | | # é»è®¤Authorizationï¼å¦ææå¤ä¸ªtokenï¼ç¨éå·åé |
| | | token-name: ${sa-token.token-name},clientid |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | Application Version: ${revision} |
| | | Spring Boot Version: ${spring-boot.version} |
| | | __________ _____.___.__ ____ ____ __________.__ |
| | | \______ \__ __ ____\__ | |__| \ \ / /_ __ ____ \______ \ | __ __ ______ |
| | | | _/ | \/ _ \/ | | | ______ \ Y / | \_/ __ \ ______ | ___/ | | | \/ ___/ |
| | | | | \ | ( <_> )____ | | /_____/ \ /| | /\ ___/ /_____/ | | | |_| | /\___ \ |
| | | |____|_ /____/ \____// ______|__| \___/ |____/ \___ > |____| |____/____//____ > |
| | | \/ \/ \/ \/ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #éè¯¯æ¶æ¯ |
| | | not.null=* å¿
须填å |
| | | user.jcaptcha.error=éªè¯ç é误 |
| | | user.jcaptcha.expire=éªè¯ç 已失æ |
| | | user.not.exists=对ä¸èµ·, æ¨çè´¦å·ï¼{0} ä¸åå¨. |
| | | user.password.not.match=ç¨æ·ä¸åå¨/å¯ç é误 |
| | | user.password.retry.limit.count=å¯ç è¾å
¥é误{0}次 |
| | | user.password.retry.limit.exceed=å¯ç è¾å
¥é误{0}次ï¼è´¦æ·éå®{1}åé |
| | | user.password.delete=对ä¸èµ·ï¼æ¨çè´¦å·ï¼{0} 已被å é¤ |
| | | user.blocked=对ä¸èµ·ï¼æ¨çè´¦å·ï¼{0} å·²ç¦ç¨ï¼è¯·è系管çå |
| | | role.blocked=è§è²å·²å°ç¦ï¼è¯·è系管çå |
| | | user.logout.success=éåºæå |
| | | length.not.valid=é¿åº¦å¿
é¡»å¨{min}å°{max}个å符ä¹é´ |
| | | user.username.not.blank=ç¨æ·åä¸è½ä¸ºç©º |
| | | user.username.not.valid=* 2å°20个æ±åãåæ¯ãæ°åæä¸åçº¿ç»æï¼ä¸å¿
须以鿰åå¼å¤´ |
| | | user.username.length.valid=è´¦æ·é¿åº¦å¿
é¡»å¨{min}å°{max}个å符ä¹é´ |
| | | user.password.not.blank=ç¨æ·å¯ç ä¸è½ä¸ºç©º |
| | | user.password.length.valid=ç¨æ·å¯ç é¿åº¦å¿
é¡»å¨{min}å°{max}个å符ä¹é´ |
| | | user.password.not.valid=* 5-50个å符 |
| | | user.password.format.valid=å¯ç å¿
é¡»å
å«å¤§å忝ãå°ååæ¯ãæ°ååç¹æ®å符 |
| | | user.email.not.valid=é®ç®±æ ¼å¼é误 |
| | | user.email.not.blank=é®ç®±ä¸è½ä¸ºç©º |
| | | user.phonenumber.not.blank=ç¨æ·ææºå·ä¸è½ä¸ºç©º |
| | | user.mobile.phone.number.not.valid=ææºå·æ ¼å¼é误 |
| | | user.login.success=ç»å½æå |
| | | user.register.success=注åæå |
| | | user.register.save.error=ä¿åç¨æ· {0} å¤±è´¥ï¼æ³¨åè´¦å·å·²åå¨ |
| | | user.register.error=注å失败ï¼è¯·è系系ç»ç®¡ç人å |
| | | user.notfound=è¯·éæ°ç»å½ |
| | | user.forcelogout=管çå强å¶éåºï¼è¯·éæ°ç»å½ |
| | | user.unknown.error=æªç¥é误ï¼è¯·éæ°ç»å½ |
| | | auth.grant.type.error=è®¤è¯æéç±»åé误 |
| | | auth.grant.type.blocked=è®¤è¯æéç±»åå·²ç¦ç¨ |
| | | auth.grant.type.not.blank=è®¤è¯æéç±»åä¸è½ä¸ºç©º |
| | | auth.clientid.not.blank=认è¯å®¢æ·ç«¯idä¸è½ä¸ºç©º |
| | | ##æä»¶ä¸ä¼ æ¶æ¯ |
| | | upload.exceed.maxSize=ä¸ä¼ çæä»¶å¤§å°è¶
åºéå¶çæä»¶å¤§å°ï¼<br/>å
许çæä»¶æå¤§å¤§å°æ¯ï¼{0}MBï¼ |
| | | upload.filename.exceed.length=ä¸ä¼ çæä»¶åæé¿{0}个å符 |
| | | ##æé |
| | | no.permission=æ¨æ²¡ææ°æ®çæéï¼è¯·è系管çåæ·»å æé [{0}] |
| | | no.create.permission=æ¨æ²¡æåå»ºæ°æ®çæéï¼è¯·è系管çåæ·»å æé [{0}] |
| | | no.update.permission=æ¨æ²¡æä¿®æ¹æ°æ®çæéï¼è¯·è系管çåæ·»å æé [{0}] |
| | | no.delete.permission=æ¨æ²¡æå 餿°æ®çæéï¼è¯·è系管çåæ·»å æé [{0}] |
| | | no.export.permission=æ¨æ²¡æå¯¼åºæ°æ®çæéï¼è¯·è系管çåæ·»å æé [{0}] |
| | | no.view.permission=æ¨æ²¡ææ¥çæ°æ®çæéï¼è¯·è系管çåæ·»å æé [{0}] |
| | | repeat.submit.message=ä¸å
许éå¤æäº¤ï¼è¯·ç¨ååè¯ |
| | | rate.limiter.message=访é®è¿äºé¢ç¹ï¼è¯·ç¨ååè¯ |
| | | sms.code.not.blank=çä¿¡éªè¯ç ä¸è½ä¸ºç©º |
| | | sms.code.retry.limit.count=çä¿¡éªè¯ç è¾å
¥é误{0}次 |
| | | sms.code.retry.limit.exceed=çä¿¡éªè¯ç è¾å
¥é误{0}次ï¼è´¦æ·éå®{1}åé |
| | | email.code.not.blank=é®ç®±éªè¯ç ä¸è½ä¸ºç©º |
| | | email.code.retry.limit.count=é®ç®±éªè¯ç è¾å
¥é误{0}次 |
| | | email.code.retry.limit.exceed=é®ç®±éªè¯ç è¾å
¥é误{0}次ï¼è´¦æ·éå®{1}åé |
| | | xcx.code.not.blank=å°ç¨åº[code]ä¸è½ä¸ºç©º |
| | | social.source.not.blank=ç¬¬ä¸æ¹ç»å½å¹³å°[source]ä¸è½ä¸ºç©º |
| | | social.code.not.blank=ç¬¬ä¸æ¹ç»å½å¹³å°[code]ä¸è½ä¸ºç©º |
| | | social.state.not.blank=ç¬¬ä¸æ¹ç»å½å¹³å°[state]ä¸è½ä¸ºç©º |
| | | ##ç§æ· |
| | | tenant.number.not.blank=ç§æ·ç¼å·ä¸è½ä¸ºç©º |
| | | tenant.not.exists=对ä¸èµ·, æ¨çç§æ·ä¸åå¨ï¼è¯·è系管çå |
| | | tenant.blocked=对ä¸èµ·ï¼æ¨çç§æ·å·²ç¦ç¨ï¼è¯·è系管çå |
| | | tenant.expired=对ä¸èµ·ï¼æ¨çç§æ·å·²è¿æï¼è¯·è系管çå |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #éè¯¯æ¶æ¯ |
| | | not.null=* Required fill in |
| | | user.jcaptcha.error=Captcha error |
| | | user.jcaptcha.expire=Captcha invalid |
| | | user.not.exists=Sorry, your account: {0} does not exist |
| | | user.password.not.match=User does not exist/Password error |
| | | user.password.retry.limit.count=Password input error {0} times |
| | | user.password.retry.limit.exceed=Password input error {0} times, account locked for {1} minutes |
| | | user.password.delete=Sorry, your accountï¼{0} has been deleted |
| | | user.blocked=Sorry, your account: {0} has been disabled. Please contact the administrator |
| | | role.blocked=Role disabledï¼please contact administrators |
| | | user.logout.success=Exit successful |
| | | length.not.valid=The length must be between {min} and {max} characters |
| | | user.username.not.blank=Username cannot be blank |
| | | user.username.not.valid=* 2 to 20 chinese characters, letters, numbers or underscores, and must start with a non number |
| | | user.username.length.valid=Account length must be between {min} and {max} characters |
| | | user.password.not.blank=Password cannot be empty |
| | | user.password.length.valid=Password length must be between {min} and {max} characters |
| | | user.password.not.valid=* 5-50 characters |
| | | user.password.format.valid=Password must contain uppercase, lowercase, digit, and special character |
| | | user.email.not.valid=Mailbox format error |
| | | user.email.not.blank=Mailbox cannot be blank |
| | | user.phonenumber.not.blank=Phone number cannot be blank |
| | | user.mobile.phone.number.not.valid=Phone number format error |
| | | user.login.success=Login successful |
| | | user.register.success=Register successful |
| | | user.register.save.error=Failed to save user {0}, The registered account already exists |
| | | user.register.error=Register failed, please contact system administrator |
| | | user.notfound=Please login again |
| | | user.forcelogout=The administrator is forced to exitï¼please login again |
| | | user.unknown.error=Unknown error, please login again |
| | | auth.grant.type.error=Auth grant type error |
| | | auth.grant.type.blocked=Auth grant type disabled |
| | | auth.grant.type.not.blank=Auth grant type cannot be blank |
| | | auth.clientid.not.blank=Auth clientid cannot be blank |
| | | ##æä»¶ä¸ä¼ æ¶æ¯ |
| | | upload.exceed.maxSize=The uploaded file size exceeds the limit file sizeï¼<br/>the maximum allowed file size isï¼{0}MBï¼ |
| | | upload.filename.exceed.length=The maximum length of uploaded file name is {0} characters |
| | | ##æé |
| | | no.permission=You do not have permission to the dataï¼please contact your administrator to add permissions [{0}] |
| | | no.create.permission=You do not have permission to create dataï¼please contact your administrator to add permissions [{0}] |
| | | no.update.permission=You do not have permission to modify dataï¼please contact your administrator to add permissions [{0}] |
| | | no.delete.permission=You do not have permission to delete dataï¼please contact your administrator to add permissions [{0}] |
| | | no.export.permission=You do not have permission to export dataï¼please contact your administrator to add permissions [{0}] |
| | | no.view.permission=You do not have permission to view dataï¼please contact your administrator to add permissions [{0}] |
| | | repeat.submit.message=Repeat submit is not allowed, please try again later |
| | | rate.limiter.message=Visit too frequently, please try again later |
| | | sms.code.not.blank=Sms code cannot be blank |
| | | sms.code.retry.limit.count=Sms code input error {0} times |
| | | sms.code.retry.limit.exceed=Sms code input error {0} times, account locked for {1} minutes |
| | | email.code.not.blank=Email code cannot be blank |
| | | email.code.retry.limit.count=Email code input error {0} times |
| | | email.code.retry.limit.exceed=Email code input error {0} times, account locked for {1} minutes |
| | | xcx.code.not.blank=Mini program [code] cannot be blank |
| | | social.source.not.blank=Social login platform [source] cannot be blank |
| | | social.code.not.blank=Social login platform [code] cannot be blank |
| | | social.state.not.blank=Social login platform [state] cannot be blank |
| | | ##ç§æ· |
| | | tenant.number.not.blank=Tenant number cannot be blank |
| | | tenant.not.exists=Sorry, your tenant does not exist. Please contact the administrator |
| | | tenant.blocked=Sorry, your tenant is disabled. Please contact the administrator |
| | | tenant.expired=Sorry, your tenant has expired. Please contact the administrator. |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | #éè¯¯æ¶æ¯ |
| | | not.null=* å¿
须填å |
| | | user.jcaptcha.error=éªè¯ç é误 |
| | | user.jcaptcha.expire=éªè¯ç 已失æ |
| | | user.not.exists=对ä¸èµ·, æ¨çè´¦å·ï¼{0} ä¸åå¨. |
| | | user.password.not.match=ç¨æ·ä¸åå¨/å¯ç é误 |
| | | user.password.retry.limit.count=å¯ç è¾å
¥é误{0}次 |
| | | user.password.retry.limit.exceed=å¯ç è¾å
¥é误{0}次ï¼è´¦æ·éå®{1}åé |
| | | user.password.delete=对ä¸èµ·ï¼æ¨çè´¦å·ï¼{0} 已被å é¤ |
| | | user.blocked=对ä¸èµ·ï¼æ¨çè´¦å·ï¼{0} å·²ç¦ç¨ï¼è¯·è系管çå |
| | | role.blocked=è§è²å·²å°ç¦ï¼è¯·è系管çå |
| | | user.logout.success=éåºæå |
| | | length.not.valid=é¿åº¦å¿
é¡»å¨{min}å°{max}个å符ä¹é´ |
| | | user.username.not.blank=ç¨æ·åä¸è½ä¸ºç©º |
| | | user.username.not.valid=* 2å°20个æ±åãåæ¯ãæ°åæä¸åçº¿ç»æï¼ä¸å¿
须以鿰åå¼å¤´ |
| | | user.username.length.valid=è´¦æ·é¿åº¦å¿
é¡»å¨{min}å°{max}个å符ä¹é´ |
| | | user.password.not.blank=ç¨æ·å¯ç ä¸è½ä¸ºç©º |
| | | user.password.length.valid=ç¨æ·å¯ç é¿åº¦å¿
é¡»å¨{min}å°{max}个å符ä¹é´ |
| | | user.password.not.valid=* 5-50个å符 |
| | | user.password.format.valid=å¯ç å¿
é¡»å
å«å¤§å忝ãå°ååæ¯ãæ°ååç¹æ®å符 |
| | | user.email.not.valid=é®ç®±æ ¼å¼é误 |
| | | user.email.not.blank=é®ç®±ä¸è½ä¸ºç©º |
| | | user.phonenumber.not.blank=ç¨æ·ææºå·ä¸è½ä¸ºç©º |
| | | user.mobile.phone.number.not.valid=ææºå·æ ¼å¼é误 |
| | | user.login.success=ç»å½æå |
| | | user.register.success=注åæå |
| | | user.register.save.error=ä¿åç¨æ· {0} å¤±è´¥ï¼æ³¨åè´¦å·å·²åå¨ |
| | | user.register.error=注å失败ï¼è¯·è系系ç»ç®¡ç人å |
| | | user.notfound=è¯·éæ°ç»å½ |
| | | user.forcelogout=管çå强å¶éåºï¼è¯·éæ°ç»å½ |
| | | user.unknown.error=æªç¥é误ï¼è¯·éæ°ç»å½ |
| | | auth.grant.type.error=è®¤è¯æéç±»åé误 |
| | | auth.grant.type.blocked=è®¤è¯æéç±»åå·²ç¦ç¨ |
| | | auth.grant.type.not.blank=è®¤è¯æéç±»åä¸è½ä¸ºç©º |
| | | auth.clientid.not.blank=认è¯å®¢æ·ç«¯idä¸è½ä¸ºç©º |
| | | ##æä»¶ä¸ä¼ æ¶æ¯ |
| | | upload.exceed.maxSize=ä¸ä¼ çæä»¶å¤§å°è¶
åºéå¶çæä»¶å¤§å°ï¼<br/>å
许çæä»¶æå¤§å¤§å°æ¯ï¼{0}MBï¼ |
| | | upload.filename.exceed.length=ä¸ä¼ çæä»¶åæé¿{0}个å符 |
| | | ##æé |
| | | no.permission=æ¨æ²¡ææ°æ®çæéï¼è¯·è系管çåæ·»å æé [{0}] |
| | | no.create.permission=æ¨æ²¡æåå»ºæ°æ®çæéï¼è¯·è系管çåæ·»å æé [{0}] |
| | | no.update.permission=æ¨æ²¡æä¿®æ¹æ°æ®çæéï¼è¯·è系管çåæ·»å æé [{0}] |
| | | no.delete.permission=æ¨æ²¡æå 餿°æ®çæéï¼è¯·è系管çåæ·»å æé [{0}] |
| | | no.export.permission=æ¨æ²¡æå¯¼åºæ°æ®çæéï¼è¯·è系管çåæ·»å æé [{0}] |
| | | no.view.permission=æ¨æ²¡ææ¥çæ°æ®çæéï¼è¯·è系管çåæ·»å æé [{0}] |
| | | repeat.submit.message=ä¸å
许éå¤æäº¤ï¼è¯·ç¨ååè¯ |
| | | rate.limiter.message=访é®è¿äºé¢ç¹ï¼è¯·ç¨ååè¯ |
| | | sms.code.not.blank=çä¿¡éªè¯ç ä¸è½ä¸ºç©º |
| | | sms.code.retry.limit.count=çä¿¡éªè¯ç è¾å
¥é误{0}次 |
| | | sms.code.retry.limit.exceed=çä¿¡éªè¯ç è¾å
¥é误{0}次ï¼è´¦æ·éå®{1}åé |
| | | email.code.not.blank=é®ç®±éªè¯ç ä¸è½ä¸ºç©º |
| | | email.code.retry.limit.count=é®ç®±éªè¯ç è¾å
¥é误{0}次 |
| | | email.code.retry.limit.exceed=é®ç®±éªè¯ç è¾å
¥é误{0}次ï¼è´¦æ·éå®{1}åé |
| | | xcx.code.not.blank=å°ç¨åº[code]ä¸è½ä¸ºç©º |
| | | social.source.not.blank=ç¬¬ä¸æ¹ç»å½å¹³å°[source]ä¸è½ä¸ºç©º |
| | | social.code.not.blank=ç¬¬ä¸æ¹ç»å½å¹³å°[code]ä¸è½ä¸ºç©º |
| | | social.state.not.blank=ç¬¬ä¸æ¹ç»å½å¹³å°[state]ä¸è½ä¸ºç©º |
| | | ##ç§æ· |
| | | tenant.number.not.blank=ç§æ·ç¼å·ä¸è½ä¸ºç©º |
| | | tenant.not.exists=对ä¸èµ·, æ¨çç§æ·ä¸åå¨ï¼è¯·è系管çå |
| | | tenant.blocked=对ä¸èµ·ï¼æ¨çç§æ·å·²ç¦ç¨ï¼è¯·è系管çå |
| | | tenant.expired=对ä¸èµ·ï¼æ¨çç§æ·å·²è¿æï¼è¯·è系管çå |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <configuration> |
| | | <property name="log.path" value="./logs"/> |
| | | <property name="console.log.pattern" |
| | | value="%cyan(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/> |
| | | <property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"/> |
| | | |
| | | <!-- æ§å¶å°è¾åº --> |
| | | <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> |
| | | <encoder> |
| | | <pattern>${console.log.pattern}</pattern> |
| | | <charset>utf-8</charset> |
| | | </encoder> |
| | | </appender> |
| | | |
| | | <!-- æ§å¶å°è¾åº --> |
| | | <appender name="file_console" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
| | | <file>${log.path}/sys-console.log</file> |
| | | <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> |
| | | <!-- æ¥å¿æä»¶åæ ¼å¼ --> |
| | | <fileNamePattern>${log.path}/sys-console.%d{yyyy-MM-dd}.log</fileNamePattern> |
| | | <!-- æ¥å¿æå¤§ 1天 --> |
| | | <maxHistory>1</maxHistory> |
| | | </rollingPolicy> |
| | | <encoder> |
| | | <pattern>${log.pattern}</pattern> |
| | | <charset>utf-8</charset> |
| | | </encoder> |
| | | <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> |
| | | <!-- è¿æ»¤ççº§å« --> |
| | | <level>INFO</level> |
| | | </filter> |
| | | </appender> |
| | | |
| | | <!-- ç³»ç»æ¥å¿è¾åº --> |
| | | <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
| | | <file>${log.path}/sys-info.log</file> |
| | | <!-- å¾ªç¯æ¿çï¼åºäºæ¶é´å建æ¥å¿æä»¶ --> |
| | | <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> |
| | | <!-- æ¥å¿æä»¶åæ ¼å¼ --> |
| | | <fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log.gz</fileNamePattern> |
| | | <!-- æ¥å¿æå¤§çåå² 60天 --> |
| | | <maxHistory>60</maxHistory> |
| | | </rollingPolicy> |
| | | <encoder> |
| | | <pattern>${log.pattern}</pattern> |
| | | </encoder> |
| | | <filter class="ch.qos.logback.classic.filter.LevelFilter"> |
| | | <!-- è¿æ»¤ççº§å« --> |
| | | <level>INFO</level> |
| | | <!-- å¹é
æ¶çæä½ï¼æ¥æ¶ï¼è®°å½ï¼ --> |
| | | <onMatch>ACCEPT</onMatch> |
| | | <!-- ä¸å¹é
æ¶çæä½ï¼æç»ï¼ä¸è®°å½ï¼ --> |
| | | <onMismatch>DENY</onMismatch> |
| | | </filter> |
| | | </appender> |
| | | |
| | | <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender"> |
| | | <file>${log.path}/sys-error.log</file> |
| | | <!-- å¾ªç¯æ¿çï¼åºäºæ¶é´å建æ¥å¿æä»¶ --> |
| | | <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> |
| | | <!-- æ¥å¿æä»¶åæ ¼å¼ --> |
| | | <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log.gz</fileNamePattern> |
| | | <!-- æ¥å¿æå¤§çåå² 60天 --> |
| | | <maxHistory>60</maxHistory> |
| | | </rollingPolicy> |
| | | <encoder> |
| | | <pattern>${log.pattern}</pattern> |
| | | </encoder> |
| | | <filter class="ch.qos.logback.classic.filter.LevelFilter"> |
| | | <!-- è¿æ»¤ççº§å« --> |
| | | <level>ERROR</level> |
| | | <!-- å¹é
æ¶çæä½ï¼æ¥æ¶ï¼è®°å½ï¼ --> |
| | | <onMatch>ACCEPT</onMatch> |
| | | <!-- ä¸å¹é
æ¶çæä½ï¼æç»ï¼ä¸è®°å½ï¼ --> |
| | | <onMismatch>DENY</onMismatch> |
| | | </filter> |
| | | </appender> |
| | | |
| | | <!-- info弿¥è¾åº --> |
| | | <appender name="async_info" class="ch.qos.logback.classic.AsyncAppender"> |
| | | <!-- ä¸ä¸¢å¤±æ¥å¿.é»è®¤ç,妿éåç80%已满,åä¼ä¸¢å¼TRACTãDEBUGãINFO级å«çæ¥å¿ --> |
| | | <discardingThreshold>0</discardingThreshold> |
| | | <!-- æ´æ¹é»è®¤çéåçæ·±åº¦,该å¼ä¼å½±åæ§è½.é»è®¤å¼ä¸º256 --> |
| | | <queueSize>512</queueSize> |
| | | <!-- æ·»å éå çappender,æå¤åªè½æ·»å ä¸ä¸ª --> |
| | | <appender-ref ref="file_info"/> |
| | | </appender> |
| | | |
| | | <!-- error弿¥è¾åº --> |
| | | <appender name="async_error" class="ch.qos.logback.classic.AsyncAppender"> |
| | | <!-- ä¸ä¸¢å¤±æ¥å¿.é»è®¤ç,妿éåç80%已满,åä¼ä¸¢å¼TRACTãDEBUGãINFO级å«çæ¥å¿ --> |
| | | <discardingThreshold>0</discardingThreshold> |
| | | <!-- æ´æ¹é»è®¤çéåçæ·±åº¦,该å¼ä¼å½±åæ§è½.é»è®¤å¼ä¸º256 --> |
| | | <queueSize>512</queueSize> |
| | | <!-- æ·»å éå çappender,æå¤åªè½æ·»å ä¸ä¸ª --> |
| | | <appender-ref ref="file_error"/> |
| | | </appender> |
| | | |
| | | <!-- æ´å skywalking æ§å¶å°è¾åº tid --> |
| | | <!-- <appender name="console" class="ch.qos.logback.core.ConsoleAppender">--> |
| | | <!-- <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">--> |
| | | <!-- <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">--> |
| | | <!-- <pattern>[%tid] ${console.log.pattern}</pattern>--> |
| | | <!-- </layout>--> |
| | | <!-- <charset>utf-8</charset>--> |
| | | <!-- </encoder>--> |
| | | <!-- </appender>--> |
| | | |
| | | <!-- æ´å skywalking æ¨éééæ¥å¿ --> |
| | | <!-- <appender name="sky_log" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">--> |
| | | <!-- <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">--> |
| | | <!-- <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">--> |
| | | <!-- <pattern>[%tid] ${console.log.pattern}</pattern>--> |
| | | <!-- </layout>--> |
| | | <!-- <charset>utf-8</charset>--> |
| | | <!-- </encoder>--> |
| | | <!-- </appender>--> |
| | | |
| | | <!--ç³»ç»æä½æ¥å¿--> |
| | | <root level="info"> |
| | | <appender-ref ref="console" /> |
| | | <appender-ref ref="async_info" /> |
| | | <appender-ref ref="async_error" /> |
| | | <appender-ref ref="file_console" /> |
| | | <!-- <appender-ref ref="sky_log"/>--> |
| | | </root> |
| | | |
| | | </configuration> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.test; |
| | | |
| | | import org.junit.jupiter.api.Assertions; |
| | | import org.junit.jupiter.api.DisplayName; |
| | | import org.junit.jupiter.api.Test; |
| | | |
| | | /** |
| | | * æè¨åå
æµè¯æ¡ä¾ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @DisplayName("æè¨åå
æµè¯æ¡ä¾") |
| | | public class AssertUnitTest { |
| | | |
| | | @DisplayName("æµè¯ assertEquals æ¹æ³") |
| | | @Test |
| | | public void testAssertEquals() { |
| | | Assertions.assertEquals("666", new String("666")); |
| | | Assertions.assertNotEquals("666", new String("666")); |
| | | } |
| | | |
| | | @DisplayName("æµè¯ assertSame æ¹æ³") |
| | | @Test |
| | | public void testAssertSame() { |
| | | Object obj = new Object(); |
| | | Object obj1 = obj; |
| | | Assertions.assertSame(obj, obj1); |
| | | Assertions.assertNotSame(obj, obj1); |
| | | } |
| | | |
| | | @DisplayName("æµè¯ assertTrue æ¹æ³") |
| | | @Test |
| | | public void testAssertTrue() { |
| | | Assertions.assertTrue(true); |
| | | Assertions.assertFalse(true); |
| | | } |
| | | |
| | | @DisplayName("æµè¯ assertNull æ¹æ³") |
| | | @Test |
| | | public void testAssertNull() { |
| | | Assertions.assertNull(null); |
| | | Assertions.assertNotNull(null); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.test; |
| | | |
| | | import org.dromara.common.web.config.properties.CaptchaProperties; |
| | | import org.junit.jupiter.api.*; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.boot.test.context.SpringBootTest; |
| | | |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * åå
æµè¯æ¡ä¾ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @SpringBootTest // æ¤æ³¨è§£åªè½å¨ springboot 主å
ä¸ä½¿ç¨ éå
å« main æ¹æ³ä¸ yml é
ç½®æä»¶ |
| | | @DisplayName("åå
æµè¯æ¡ä¾") |
| | | public class DemoUnitTest { |
| | | |
| | | @Autowired |
| | | private CaptchaProperties captchaProperties; |
| | | |
| | | @DisplayName("æµè¯ @SpringBootTest @Test @DisplayName 注解") |
| | | @Test |
| | | public void testTest() { |
| | | System.out.println(captchaProperties); |
| | | } |
| | | |
| | | @Disabled |
| | | @DisplayName("æµè¯ @Disabled 注解") |
| | | @Test |
| | | public void testDisabled() { |
| | | System.out.println(captchaProperties); |
| | | } |
| | | |
| | | @Timeout(value = 2L, unit = TimeUnit.SECONDS) |
| | | @DisplayName("æµè¯ @Timeout 注解") |
| | | @Test |
| | | public void testTimeout() throws InterruptedException { |
| | | Thread.sleep(3000); |
| | | System.out.println(captchaProperties); |
| | | } |
| | | |
| | | |
| | | @DisplayName("æµè¯ @RepeatedTest 注解") |
| | | @RepeatedTest(3) |
| | | public void testRepeatedTest() { |
| | | System.out.println(666); |
| | | } |
| | | |
| | | @BeforeAll |
| | | public static void testBeforeAll() { |
| | | System.out.println("@BeforeAll =================="); |
| | | } |
| | | |
| | | @BeforeEach |
| | | public void testBeforeEach() { |
| | | System.out.println("@BeforeEach =================="); |
| | | } |
| | | |
| | | @AfterEach |
| | | public void testAfterEach() { |
| | | System.out.println("@AfterEach =================="); |
| | | } |
| | | |
| | | @AfterAll |
| | | public static void testAfterAll() { |
| | | System.out.println("@AfterAll =================="); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.test; |
| | | |
| | | import org.dromara.common.core.enums.UserType; |
| | | import org.junit.jupiter.api.AfterEach; |
| | | import org.junit.jupiter.api.BeforeEach; |
| | | import org.junit.jupiter.api.DisplayName; |
| | | import org.junit.jupiter.params.ParameterizedTest; |
| | | import org.junit.jupiter.params.provider.EnumSource; |
| | | import org.junit.jupiter.params.provider.MethodSource; |
| | | import org.junit.jupiter.params.provider.NullSource; |
| | | import org.junit.jupiter.params.provider.ValueSource; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.stream.Stream; |
| | | |
| | | /** |
| | | * 另忰åå
æµè¯æ¡ä¾ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @DisplayName("另忰åå
æµè¯æ¡ä¾") |
| | | public class ParamUnitTest { |
| | | |
| | | @DisplayName("æµè¯ @ValueSource 注解") |
| | | @ParameterizedTest |
| | | @ValueSource(strings = {"t1", "t2", "t3"}) |
| | | public void testValueSource(String str) { |
| | | System.out.println(str); |
| | | } |
| | | |
| | | @DisplayName("æµè¯ @NullSource 注解") |
| | | @ParameterizedTest |
| | | @NullSource |
| | | public void testNullSource(String str) { |
| | | System.out.println(str); |
| | | } |
| | | |
| | | @DisplayName("æµè¯ @EnumSource 注解") |
| | | @ParameterizedTest |
| | | @EnumSource(UserType.class) |
| | | public void testEnumSource(UserType type) { |
| | | System.out.println(type.getUserType()); |
| | | } |
| | | |
| | | @DisplayName("æµè¯ @MethodSource 注解") |
| | | @ParameterizedTest |
| | | @MethodSource("getParam") |
| | | public void testMethodSource(String str) { |
| | | System.out.println(str); |
| | | } |
| | | |
| | | public static Stream<String> getParam() { |
| | | List<String> list = new ArrayList<>(); |
| | | list.add("t1"); |
| | | list.add("t2"); |
| | | list.add("t3"); |
| | | return list.stream(); |
| | | } |
| | | |
| | | @BeforeEach |
| | | public void testBeforeEach() { |
| | | System.out.println("@BeforeEach =================="); |
| | | } |
| | | |
| | | @AfterEach |
| | | public void testAfterEach() { |
| | | System.out.println("@AfterEach =================="); |
| | | } |
| | | |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.test; |
| | | |
| | | import org.junit.jupiter.api.*; |
| | | import org.springframework.boot.test.context.SpringBootTest; |
| | | |
| | | /** |
| | | * æ ç¾åå
æµè¯æ¡ä¾ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @SpringBootTest |
| | | @DisplayName("æ ç¾åå
æµè¯æ¡ä¾") |
| | | public class TagUnitTest { |
| | | |
| | | @Tag("dev") |
| | | @DisplayName("æµè¯ @Tag dev") |
| | | @Test |
| | | public void testTagDev() { |
| | | System.out.println("dev"); |
| | | } |
| | | |
| | | @Tag("prod") |
| | | @DisplayName("æµè¯ @Tag prod") |
| | | @Test |
| | | public void testTagProd() { |
| | | System.out.println("prod"); |
| | | } |
| | | |
| | | @Tag("local") |
| | | @DisplayName("æµè¯ @Tag local") |
| | | @Test |
| | | public void testTagLocal() { |
| | | System.out.println("local"); |
| | | } |
| | | |
| | | @Tag("exclude") |
| | | @DisplayName("æµè¯ @Tag exclude") |
| | | @Test |
| | | public void testTagExclude() { |
| | | System.out.println("exclude"); |
| | | } |
| | | |
| | | @BeforeEach |
| | | public void testBeforeEach() { |
| | | System.out.println("@BeforeEach =================="); |
| | | } |
| | | |
| | | @AfterEach |
| | | public void testAfterEach() { |
| | | System.out.println("@AfterEach =================="); |
| | | } |
| | | |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-vue-plus</artifactId> |
| | | <version>5.5.3</version> |
| | | </parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>5.5.3</version> |
| | | <packaging>pom</packaging> |
| | | <description>common éç¨æ¨¡å</description> |
| | | <modules> |
| | | <module>ruoyi-common-bom</module> |
| | | <module>ruoyi-common-social</module> |
| | | <module>ruoyi-common-core</module> |
| | | <module>ruoyi-common-doc</module> |
| | | <module>ruoyi-common-excel</module> |
| | | <module>ruoyi-common-idempotent</module> |
| | | <module>ruoyi-common-job</module> |
| | | <module>ruoyi-common-log</module> |
| | | <module>ruoyi-common-mail</module> |
| | | <module>ruoyi-common-mybatis</module> |
| | | <module>ruoyi-common-oss</module> |
| | | <module>ruoyi-common-ratelimiter</module> |
| | | <module>ruoyi-common-redis</module> |
| | | <module>ruoyi-common-satoken</module> |
| | | <module>ruoyi-common-security</module> |
| | | <module>ruoyi-common-sms</module> |
| | | <module>ruoyi-common-web</module> |
| | | <module>ruoyi-common-translation</module> |
| | | <module>ruoyi-common-sensitive</module> |
| | | <module>ruoyi-common-json</module> |
| | | <module>ruoyi-common-encrypt</module> |
| | | <module>ruoyi-common-tenant</module> |
| | | <module>ruoyi-common-websocket</module> |
| | | <module>ruoyi-common-sse</module> |
| | | </modules> |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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"> |
| | | <parent> |
| | | <artifactId>ruoyi-vue-plus</artifactId> |
| | | <groupId>org.dromara</groupId> |
| | | <version>${revision}</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <modules> |
| | | <module>ruoyi-common-bom</module> |
| | | <module>ruoyi-common-social</module> |
| | | <module>ruoyi-common-core</module> |
| | | <module>ruoyi-common-doc</module> |
| | | <module>ruoyi-common-excel</module> |
| | | <module>ruoyi-common-idempotent</module> |
| | | <module>ruoyi-common-job</module> |
| | | <module>ruoyi-common-log</module> |
| | | <module>ruoyi-common-mail</module> |
| | | <module>ruoyi-common-mybatis</module> |
| | | <module>ruoyi-common-oss</module> |
| | | <module>ruoyi-common-ratelimiter</module> |
| | | <module>ruoyi-common-redis</module> |
| | | <module>ruoyi-common-satoken</module> |
| | | <module>ruoyi-common-security</module> |
| | | <module>ruoyi-common-sms</module> |
| | | <module>ruoyi-common-web</module> |
| | | <module>ruoyi-common-translation</module> |
| | | <module>ruoyi-common-sensitive</module> |
| | | <module>ruoyi-common-json</module> |
| | | <module>ruoyi-common-encrypt</module> |
| | | <module>ruoyi-common-tenant</module> |
| | | <module>ruoyi-common-websocket</module> |
| | | <module>ruoyi-common-sse</module> |
| | | </modules> |
| | | |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <packaging>pom</packaging> |
| | | |
| | | <description> |
| | | common éç¨æ¨¡å |
| | | </description> |
| | | |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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> |
| | | |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-bom</artifactId> |
| | | <version>${revision}</version> |
| | | <packaging>pom</packaging> |
| | | |
| | | <description> |
| | | ruoyi-common-bom commonä¾èµé¡¹ |
| | | </description> |
| | | |
| | | <properties> |
| | | <revision>5.5.3</revision> |
| | | </properties> |
| | | |
| | | <dependencyManagement> |
| | | <dependencies> |
| | | <!-- æ ¸å¿æ¨¡å --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- æ¥å£æ¨¡å --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-doc</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- excel --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-excel</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- å¹ç --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-idempotent</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- è°åº¦æ¨¡å --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-job</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- æ¥å¿è®°å½ --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-log</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- é®ä»¶æå¡ --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-mail</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- æ°æ®åºæå¡ --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-mybatis</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- OSS --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-oss</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- éæµ --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-ratelimiter</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- ç¼åæå¡ --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-redis</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- satoken --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-satoken</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- å®å
¨æ¨¡å --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-security</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- ç信模å --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-sms</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-social</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- webæå¡ --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-web</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- ç¿»è¯æ¨¡å --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-translation</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- è±ææ¨¡å --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-sensitive</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- åºå忍¡å --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-json</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- æ°æ®åºå è§£å¯æ¨¡å --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-encrypt</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- ç§æ·æ¨¡å --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-tenant</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- WebSocket模å --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-websocket</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | <!-- SSE模å --> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-sse</artifactId> |
| | | <version>${revision}</version> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | </dependencyManagement> |
| | | |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>5.5.3</version> |
| | | </parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | <version>5.5.3</version> |
| | | <description>ruoyi-common-core æ ¸å¿æ¨¡å</description> |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.springframework</groupId> |
| | | <artifactId>spring-context-support</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework</groupId> |
| | | <artifactId>spring-web</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-aop</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.apache.commons</groupId> |
| | | <artifactId>commons-lang3</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>jakarta.servlet</groupId> |
| | | <artifactId>jakarta.servlet-api</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>cn.hutool</groupId> |
| | | <artifactId>hutool-core</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>cn.hutool</groupId> |
| | | <artifactId>hutool-http</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>cn.hutool</groupId> |
| | | <artifactId>hutool-extra</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.projectlombok</groupId> |
| | | <artifactId>lombok</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-configuration-processor</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-properties-migrator</artifactId> |
| | | <scope>runtime</scope> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>io.github.linpeilie</groupId> |
| | | <artifactId>mapstruct-plus-spring-boot-starter</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.lionsoul</groupId> |
| | | <artifactId>ip2region</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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"> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>${revision}</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | |
| | | <description> |
| | | ruoyi-common-core æ ¸å¿æ¨¡å |
| | | </description> |
| | | |
| | | <dependencies> |
| | | <!-- Springæ¡æ¶åºæ¬çæ ¸å¿å·¥å
· --> |
| | | <dependency> |
| | | <groupId>org.springframework</groupId> |
| | | <artifactId>spring-context-support</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- SpringWeb模å --> |
| | | <dependency> |
| | | <groupId>org.springframework</groupId> |
| | | <artifactId>spring-web</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-aop</artifactId> |
| | | </dependency> |
| | | |
| | | <!--常ç¨å·¥å
·ç±» --> |
| | | <dependency> |
| | | <groupId>org.apache.commons</groupId> |
| | | <artifactId>commons-lang3</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- servletå
--> |
| | | <dependency> |
| | | <groupId>jakarta.servlet</groupId> |
| | | <artifactId>jakarta.servlet-api</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>cn.hutool</groupId> |
| | | <artifactId>hutool-core</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>cn.hutool</groupId> |
| | | <artifactId>hutool-http</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>cn.hutool</groupId> |
| | | <artifactId>hutool-extra</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.projectlombok</groupId> |
| | | <artifactId>lombok</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- èªå¨çæYMLé
ç½®å
³èJSONæä»¶ --> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-configuration-processor</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-properties-migrator</artifactId> |
| | | <scope>runtime</scope> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>io.github.linpeilie</groupId> |
| | | <artifactId>mapstruct-plus-spring-boot-starter</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- 离线IPå°åå®ä½åº --> |
| | | <dependency> |
| | | <groupId>org.lionsoul</groupId> |
| | | <artifactId>ip2region</artifactId> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.config; |
| | | |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.context.annotation.EnableAspectJAutoProxy; |
| | | import org.springframework.scheduling.annotation.EnableAsync; |
| | | |
| | | /** |
| | | * ç¨åºæ³¨è§£é
ç½® |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @AutoConfiguration |
| | | @EnableAspectJAutoProxy |
| | | @EnableAsync(proxyTargetClass = true) |
| | | public class ApplicationConfig { |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.config; |
| | | |
| | | import jakarta.annotation.PreDestroy; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.concurrent.BasicThreadFactory; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.core.task.VirtualThreadTaskExecutor; |
| | | |
| | | import java.util.concurrent.*; |
| | | |
| | | /** |
| | | * çº¿ç¨æ± é
ç½® |
| | | * |
| | | * @author Lion Li |
| | | **/ |
| | | @Slf4j |
| | | @AutoConfiguration |
| | | public class ThreadPoolConfig { |
| | | |
| | | /** |
| | | * æ ¸å¿çº¿ç¨æ° = cpu æ ¸å¿æ° + 1 |
| | | */ |
| | | private final int core = Runtime.getRuntime().availableProcessors() + 1; |
| | | |
| | | private ScheduledExecutorService scheduledExecutorService; |
| | | |
| | | /** |
| | | * æ§è¡å¨ææ§æå®æ¶ä»»å¡ |
| | | */ |
| | | @Bean(name = "scheduledExecutorService") |
| | | protected ScheduledExecutorService scheduledExecutorService() { |
| | | // daemon å¿
须为 true |
| | | BasicThreadFactory.Builder builder = new BasicThreadFactory.Builder().daemon(true); |
| | | if (SpringUtils.isVirtual()) { |
| | | builder.namingPattern("virtual-schedule-pool-%d").wrappedFactory(new VirtualThreadTaskExecutor().getVirtualThreadFactory()); |
| | | } else { |
| | | builder.namingPattern("schedule-pool-%d"); |
| | | } |
| | | ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(core, |
| | | builder.build(), |
| | | new ThreadPoolExecutor.CallerRunsPolicy()) { |
| | | @Override |
| | | protected void afterExecute(Runnable r, Throwable t) { |
| | | super.afterExecute(r, t); |
| | | printException(r, t); |
| | | } |
| | | }; |
| | | this.scheduledExecutorService = scheduledThreadPoolExecutor; |
| | | return scheduledThreadPoolExecutor; |
| | | } |
| | | |
| | | /** |
| | | * 鿝äºä»¶ |
| | | * åæ¢çº¿ç¨æ± |
| | | * å
使ç¨shutdown, åæ¢æ¥æ¶æ°ä»»å¡å¹¶å°è¯å®æææå·²åå¨ä»»å¡. |
| | | * 妿è¶
æ¶, åè°ç¨shutdownNow, åæ¶å¨workQueueä¸Pendingçä»»å¡,并䏿ææé»å¡å½æ°. |
| | | * 妿ä»ç¶è¶
æï¼åå¼·å¶éåº. |
| | | * å¦å¯¹å¨shutdownæ¶çº¿ç¨æ¬èº«è¢«è°ç¨ä¸æåäºå¤ç. |
| | | */ |
| | | @PreDestroy |
| | | public void destroy() { |
| | | try { |
| | | log.info("====å
³éåå°ä»»å¡ä»»å¡çº¿ç¨æ± ===="); |
| | | ScheduledExecutorService pool = scheduledExecutorService; |
| | | if (pool != null && !pool.isShutdown()) { |
| | | pool.shutdown(); |
| | | try { |
| | | if (!pool.awaitTermination(120, TimeUnit.SECONDS)) { |
| | | pool.shutdownNow(); |
| | | if (!pool.awaitTermination(120, TimeUnit.SECONDS)) { |
| | | log.info("Pool did not terminate"); |
| | | } |
| | | } |
| | | } catch (InterruptedException ie) { |
| | | pool.shutdownNow(); |
| | | Thread.currentThread().interrupt(); |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | log.error(e.getMessage(), e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æå°çº¿ç¨å¼å¸¸ä¿¡æ¯ |
| | | */ |
| | | public static void printException(Runnable r, Throwable t) { |
| | | if (t == null && r instanceof Future<?>) { |
| | | try { |
| | | Future<?> future = (Future<?>) r; |
| | | if (future.isDone()) { |
| | | future.get(); |
| | | } |
| | | } catch (CancellationException ce) { |
| | | t = ce; |
| | | } catch (ExecutionException ee) { |
| | | t = ee.getCause(); |
| | | } catch (InterruptedException ie) { |
| | | Thread.currentThread().interrupt(); |
| | | } |
| | | } |
| | | if (t != null) { |
| | | log.error(t.getMessage(), t); |
| | | } |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.config; |
| | | |
| | | import jakarta.validation.Validator; |
| | | import org.hibernate.validator.HibernateValidator; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration; |
| | | import org.springframework.context.MessageSource; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; |
| | | |
| | | import java.util.Properties; |
| | | |
| | | /** |
| | | * æ ¡éªæ¡æ¶é
置类 |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @AutoConfiguration(before = ValidationAutoConfiguration.class) |
| | | public class ValidatorConfig { |
| | | |
| | | /** |
| | | * é
ç½®æ ¡éªæ¡æ¶ å¿«éå¤±è´¥æ¨¡å¼ |
| | | */ |
| | | @Bean |
| | | public Validator validator(MessageSource messageSource) { |
| | | try (LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean()) { |
| | | // å½é
å |
| | | factoryBean.setValidationMessageSource(messageSource); |
| | | // è®¾ç½®ä½¿ç¨ HibernateValidator æ ¡éªå¨ |
| | | factoryBean.setProviderClass(HibernateValidator.class); |
| | | Properties properties = new Properties(); |
| | | // 设置快é失败模å¼ï¼fail-fastï¼ï¼å³æ ¡éªè¿ç¨ä¸ä¸æ¦éå°å¤±è´¥ï¼ç«å³åæ¢å¹¶è¿åé误 |
| | | properties.setProperty("hibernate.validator.fail_fast", "true"); |
| | | factoryBean.setValidationProperties(properties); |
| | | // å è½½é
ç½® |
| | | factoryBean.afterPropertiesSet(); |
| | | return factoryBean.getValidator(); |
| | | } |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.constant; |
| | | |
| | | /** |
| | | * ç¼åçkey 常é |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public interface CacheConstants { |
| | | |
| | | /** |
| | | * å¨çº¿ç¨æ· redis key |
| | | */ |
| | | String ONLINE_TOKEN_KEY = "online_tokens:"; |
| | | |
| | | /** |
| | | * åæ°ç®¡ç cache key |
| | | */ |
| | | String SYS_CONFIG_KEY = "sys_config:"; |
| | | |
| | | /** |
| | | * åå
¸ç®¡ç cache key |
| | | */ |
| | | String SYS_DICT_KEY = "sys_dict:"; |
| | | |
| | | /** |
| | | * ç»å½è´¦æ·å¯ç éè¯¯æ¬¡æ° redis key |
| | | */ |
| | | String PWD_ERR_CNT_KEY = "pwd_err_cnt:"; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.constant; |
| | | |
| | | /** |
| | | * ç¼åç»å称常é |
| | | * <p> |
| | | * key æ ¼å¼ä¸º cacheNames#ttl#maxIdleTime#maxSize#local |
| | | * <p> |
| | | * ttl è¿ææ¶é´ å¦æè®¾ç½®ä¸º0åä¸è¿æ é»è®¤ä¸º0 |
| | | * maxIdleTime æå¤§ç©ºé²æ¶é´ æ ¹æ®LRUç®æ³æ¸
çç©ºé²æ°æ® å¦æè®¾ç½®ä¸º0å䏿£æµ é»è®¤ä¸º0 |
| | | * maxSize ç»æå¤§é¿åº¦ æ ¹æ®LRUç®æ³æ¸
çæº¢åºæ°æ® å¦æè®¾ç½®ä¸º0åæ éé¿ é»è®¤ä¸º0 |
| | | * local é»è®¤å¼å¯æ¬å°ç¼å为1 å
³éæ¬å°ç¼å为0 |
| | | * <p> |
| | | * ä¾å: test#60sãtest#0#60sãtest#0#1m#1000ãtest#1h#0#500ãtest#1h#0#500#0 |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public interface CacheNames { |
| | | |
| | | /** |
| | | * æ¼ç¤ºæ¡ä¾ |
| | | */ |
| | | String DEMO_CACHE = "demo:cache#60s#10m#20"; |
| | | |
| | | /** |
| | | * ç³»ç»é
ç½® |
| | | */ |
| | | String SYS_CONFIG = "sys_config"; |
| | | |
| | | /** |
| | | * æ°æ®åå
¸ |
| | | */ |
| | | String SYS_DICT = "sys_dict"; |
| | | |
| | | /** |
| | | * æ°æ®åå
¸ç±»å |
| | | */ |
| | | String SYS_DICT_TYPE = "sys_dict_type"; |
| | | |
| | | /** |
| | | * ç§æ· |
| | | */ |
| | | String SYS_TENANT = GlobalConstants.GLOBAL_REDIS_KEY + "sys_tenant#30d"; |
| | | |
| | | /** |
| | | * 客æ·ç«¯ |
| | | */ |
| | | String SYS_CLIENT = GlobalConstants.GLOBAL_REDIS_KEY + "sys_client#30d"; |
| | | |
| | | /** |
| | | * ç¨æ·è´¦æ· |
| | | */ |
| | | String SYS_USER_NAME = "sys_user_name#30d"; |
| | | |
| | | /** |
| | | * ç¨æ·åç§° |
| | | */ |
| | | String SYS_NICKNAME = "sys_nickname#30d"; |
| | | |
| | | /** |
| | | * é¨é¨ |
| | | */ |
| | | String SYS_DEPT = "sys_dept#30d"; |
| | | |
| | | /** |
| | | * OSSå
容 |
| | | */ |
| | | String SYS_OSS = "sys_oss#30d"; |
| | | |
| | | /** |
| | | * è§è²èªå®ä¹æé |
| | | */ |
| | | String SYS_ROLE_CUSTOM = "sys_role_custom#30d"; |
| | | |
| | | /** |
| | | * é¨é¨å以䏿é |
| | | */ |
| | | String SYS_DEPT_AND_CHILD = "sys_dept_and_child#30d"; |
| | | |
| | | /** |
| | | * OSSé
ç½® |
| | | */ |
| | | String SYS_OSS_CONFIG = GlobalConstants.GLOBAL_REDIS_KEY + "sys_oss_config"; |
| | | |
| | | /** |
| | | * å¨çº¿ç¨æ· |
| | | */ |
| | | String ONLINE_TOKEN = "online_tokens"; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.constant; |
| | | |
| | | /** |
| | | * éç¨å¸¸éä¿¡æ¯ |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | public interface Constants { |
| | | |
| | | /** |
| | | * UTF-8 å符é |
| | | */ |
| | | String UTF8 = "UTF-8"; |
| | | |
| | | /** |
| | | * GBK å符é |
| | | */ |
| | | String GBK = "GBK"; |
| | | |
| | | /** |
| | | * www主å |
| | | */ |
| | | String WWW = "www."; |
| | | |
| | | /** |
| | | * httpè¯·æ± |
| | | */ |
| | | String HTTP = "http://"; |
| | | |
| | | /** |
| | | * httpsè¯·æ± |
| | | */ |
| | | String HTTPS = "https://"; |
| | | |
| | | /** |
| | | * éç¨æåæ è¯ |
| | | */ |
| | | String SUCCESS = "0"; |
| | | |
| | | /** |
| | | * éç¨å¤±è´¥æ è¯ |
| | | */ |
| | | String FAIL = "1"; |
| | | |
| | | /** |
| | | * ç»å½æå |
| | | */ |
| | | String LOGIN_SUCCESS = "Success"; |
| | | |
| | | /** |
| | | * 注é |
| | | */ |
| | | String LOGOUT = "Logout"; |
| | | |
| | | /** |
| | | * 注å |
| | | */ |
| | | String REGISTER = "Register"; |
| | | |
| | | /** |
| | | * ç»å½å¤±è´¥ |
| | | */ |
| | | String LOGIN_FAIL = "Error"; |
| | | |
| | | /** |
| | | * éªè¯ç æææï¼åéï¼ |
| | | */ |
| | | Integer CAPTCHA_EXPIRATION = 2; |
| | | |
| | | /** |
| | | * 顶级ç¶çº§id |
| | | */ |
| | | Long TOP_PARENT_ID = 0L; |
| | | |
| | | /** |
| | | * å å¯å¤´ |
| | | */ |
| | | String ENCRYPT_HEADER = "ENC_"; |
| | | |
| | | } |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.constant; |
| | | |
| | | /** |
| | | * å
¨å±çkey常é (ä¸å¡æ å
³çkey) |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public interface GlobalConstants { |
| | | |
| | | /** |
| | | * å
¨å± redis key (ä¸å¡æ å
³çkey) |
| | | */ |
| | | String GLOBAL_REDIS_KEY = "global:"; |
| | | |
| | | /** |
| | | * éªè¯ç redis key |
| | | */ |
| | | String CAPTCHA_CODE_KEY = GLOBAL_REDIS_KEY + "captcha_codes:"; |
| | | |
| | | /** |
| | | * é²éæäº¤ redis key |
| | | */ |
| | | String REPEAT_SUBMIT_KEY = GLOBAL_REDIS_KEY + "repeat_submit:"; |
| | | |
| | | /** |
| | | * éæµ redis key |
| | | */ |
| | | String RATE_LIMIT_KEY = GLOBAL_REDIS_KEY + "rate_limit:"; |
| | | |
| | | /** |
| | | * 䏿¹è®¤è¯ redis key |
| | | */ |
| | | String SOCIAL_AUTH_CODE_KEY = GLOBAL_REDIS_KEY + "social_auth_codes:"; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.constant; |
| | | |
| | | /** |
| | | * è¿åç¶æç |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public interface HttpStatus { |
| | | /** |
| | | * æä½æå |
| | | */ |
| | | int SUCCESS = 200; |
| | | |
| | | /** |
| | | * 对象å建æå |
| | | */ |
| | | int CREATED = 201; |
| | | |
| | | /** |
| | | * 请æ±å·²ç»è¢«æ¥å |
| | | */ |
| | | int ACCEPTED = 202; |
| | | |
| | | /** |
| | | * æä½å·²ç»æ§è¡æåï¼ä½æ¯æ²¡æè¿åæ°æ® |
| | | */ |
| | | int NO_CONTENT = 204; |
| | | |
| | | /** |
| | | * èµæºå·²è¢«ç§»é¤ |
| | | */ |
| | | int MOVED_PERM = 301; |
| | | |
| | | /** |
| | | * éå®å |
| | | */ |
| | | int SEE_OTHER = 303; |
| | | |
| | | /** |
| | | * èµæºæ²¡æè¢«ä¿®æ¹ |
| | | */ |
| | | int NOT_MODIFIED = 304; |
| | | |
| | | /** |
| | | * åæ°å表é误ï¼ç¼ºå°ï¼æ ¼å¼ä¸å¹é
ï¼ |
| | | */ |
| | | int BAD_REQUEST = 400; |
| | | |
| | | /** |
| | | * æªææ |
| | | */ |
| | | int UNAUTHORIZED = 401; |
| | | |
| | | /** |
| | | * 访é®åéï¼ææè¿æ |
| | | */ |
| | | int FORBIDDEN = 403; |
| | | |
| | | /** |
| | | * èµæºï¼æå¡æªæ¾å° |
| | | */ |
| | | int NOT_FOUND = 404; |
| | | |
| | | /** |
| | | * ä¸å
许çhttpæ¹æ³ |
| | | */ |
| | | int BAD_METHOD = 405; |
| | | |
| | | /** |
| | | * èµæºå²çªï¼æè
èµæºè¢«é |
| | | */ |
| | | int CONFLICT = 409; |
| | | |
| | | /** |
| | | * 䏿¯æçæ°æ®ï¼åªä½ç±»å |
| | | */ |
| | | int UNSUPPORTED_TYPE = 415; |
| | | |
| | | /** |
| | | * ç³»ç»å
é¨é误 |
| | | */ |
| | | int ERROR = 500; |
| | | |
| | | /** |
| | | * æ¥å£æªå®ç° |
| | | */ |
| | | int NOT_IMPLEMENTED = 501; |
| | | |
| | | /** |
| | | * ç³»ç»è¦åæ¶æ¯ |
| | | */ |
| | | int WARN = 601; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.constant; |
| | | |
| | | import cn.hutool.core.lang.RegexPool; |
| | | |
| | | /** |
| | | * å¸¸ç¨æ£å表达å¼å符串 |
| | | * <p> |
| | | * å¸¸ç¨æ£å表达å¼éåï¼æ´å¤æ£åè§: https://any86.github.io/any-rule/ |
| | | * |
| | | * @author Feng |
| | | */ |
| | | public interface RegexConstants extends RegexPool { |
| | | |
| | | /** |
| | | * åå
¸ç±»åå¿
须以忝å¼å¤´ï¼ä¸åªè½ä¸ºï¼å°ååæ¯ï¼æ°åï¼ä¸æ»çº¿ï¼ |
| | | */ |
| | | String DICTIONARY_TYPE = "^[a-z][a-z0-9_]*$"; |
| | | |
| | | /** |
| | | * æéæ è¯å¿
须符å以䏿 ¼å¼ï¼ |
| | | * 1. æ åæ ¼å¼ï¼xxx:yyy:zzz |
| | | * - 第ä¸é¨åï¼xxxï¼ï¼åªè½å
å«åæ¯ãæ°ååä¸å线ï¼_ï¼ï¼ä¸è½ä½¿ç¨ `*` |
| | | * - 第äºé¨åï¼yyyï¼ï¼å¯ä»¥å
å«åæ¯ãæ°åãä¸å线ï¼_ï¼å `*` |
| | | * - 第ä¸é¨åï¼zzzï¼ï¼å¯ä»¥å
å«åæ¯ãæ°åãä¸å线ï¼_ï¼å `*` |
| | | * 2. å
许空å符串ï¼""ï¼ï¼è¡¨ç¤ºæ²¡ææéæ è¯ |
| | | */ |
| | | String PERMISSION_STRING = "^$|^[a-zA-Z0-9_]+:[a-zA-Z0-9_*]+:[a-zA-Z0-9_*]+$"; |
| | | |
| | | /** |
| | | * 身份è¯å·ç ï¼å6ä½ï¼ |
| | | */ |
| | | String ID_CARD_LAST_6 = "^(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$"; |
| | | |
| | | /** |
| | | * QQå·ç |
| | | */ |
| | | String QQ_NUMBER = "^[1-9][0-9]\\d{4,9}$"; |
| | | |
| | | /** |
| | | * 鮿¿ç¼ç |
| | | */ |
| | | String POSTAL_CODE = "^[1-9]\\d{5}$"; |
| | | |
| | | /** |
| | | * 注åè´¦å· |
| | | */ |
| | | String ACCOUNT = "^[a-zA-Z][a-zA-Z0-9_]{4,15}$"; |
| | | |
| | | /** |
| | | * å¯ç ï¼å
å«è³å°8个å符ï¼å
æ¬å¤§å忝ãå°ååæ¯ãæ°ååç¹æ®å符 |
| | | */ |
| | | String PASSWORD = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$"; |
| | | |
| | | /** |
| | | * éç¨ç¶æï¼0表示æ£å¸¸ï¼1表示åç¨ï¼ |
| | | */ |
| | | String STATUS = "^[01]$"; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.constant; |
| | | |
| | | /** |
| | | * ç³»ç»å¸¸éä¿¡æ¯ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public interface SystemConstants { |
| | | |
| | | /** |
| | | * æ£å¸¸ç¶æ |
| | | */ |
| | | String NORMAL = "0"; |
| | | |
| | | /** |
| | | * å¼å¸¸ç¶æ |
| | | */ |
| | | String DISABLE = "1"; |
| | | |
| | | /** |
| | | * æ¯å¦ä¸ºç³»ç»é»è®¤ï¼æ¯ï¼ |
| | | */ |
| | | String YES = "Y"; |
| | | |
| | | /** |
| | | * æ¯å¦ä¸ºç³»ç»é»è®¤ï¼å¦ï¼ |
| | | */ |
| | | String NO = "N"; |
| | | |
| | | /** |
| | | * æ¯å¦èåå¤é¾ï¼æ¯ï¼ |
| | | */ |
| | | String YES_FRAME = "0"; |
| | | |
| | | /** |
| | | * æ¯å¦èåå¤é¾ï¼å¦ï¼ |
| | | */ |
| | | String NO_FRAME = "1"; |
| | | |
| | | /** |
| | | * èåç±»åï¼ç®å½ï¼ |
| | | */ |
| | | String TYPE_DIR = "M"; |
| | | |
| | | /** |
| | | * èåç±»åï¼èåï¼ |
| | | */ |
| | | String TYPE_MENU = "C"; |
| | | |
| | | /** |
| | | * èåç±»åï¼æé®ï¼ |
| | | */ |
| | | String TYPE_BUTTON = "F"; |
| | | |
| | | /** |
| | | * Layoutç»ä»¶æ è¯ |
| | | */ |
| | | String LAYOUT = "Layout"; |
| | | |
| | | /** |
| | | * ParentViewç»ä»¶æ è¯ |
| | | */ |
| | | String PARENT_VIEW = "ParentView"; |
| | | |
| | | /** |
| | | * InnerLinkç»ä»¶æ è¯ |
| | | */ |
| | | String INNER_LINK = "InnerLink"; |
| | | |
| | | /** |
| | | * è¶
级管çåID |
| | | */ |
| | | Long SUPER_ADMIN_ID = 1L; |
| | | |
| | | /** |
| | | * æ ¹é¨é¨ç¥çº§å表 |
| | | */ |
| | | String ROOT_DEPT_ANCESTORS = "0"; |
| | | |
| | | /** |
| | | * é»è®¤é¨é¨ ID |
| | | */ |
| | | Long DEFAULT_DEPT_ID = 100L; |
| | | |
| | | /** |
| | | * æé¤ææå±æ§å段 |
| | | */ |
| | | String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" }; |
| | | |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.constant; |
| | | |
| | | /** |
| | | * ç§æ·å¸¸éä¿¡æ¯ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public interface TenantConstants { |
| | | |
| | | /** |
| | | * è¶
级管çåID |
| | | */ |
| | | Long SUPER_ADMIN_ID = 1L; |
| | | |
| | | /** |
| | | * è¶
级管çåè§è² roleKey |
| | | */ |
| | | String SUPER_ADMIN_ROLE_KEY = "superadmin"; |
| | | |
| | | /** |
| | | * ç§æ·ç®¡çåè§è² roleKey |
| | | */ |
| | | String TENANT_ADMIN_ROLE_KEY = "admin"; |
| | | |
| | | /** |
| | | * ç§æ·ç®¡çåè§è²åç§° |
| | | */ |
| | | String TENANT_ADMIN_ROLE_NAME = "管çå"; |
| | | |
| | | /** |
| | | * é»è®¤ç§æ·ID |
| | | */ |
| | | String DEFAULT_TENANT_ID = "000000"; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain; |
| | | |
| | | import org.dromara.common.core.constant.HttpStatus; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * ååºä¿¡æ¯ä¸»ä½ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | public class R<T> implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * æå |
| | | */ |
| | | public static final int SUCCESS = 200; |
| | | |
| | | /** |
| | | * 失败 |
| | | */ |
| | | public static final int FAIL = 500; |
| | | |
| | | private int code; |
| | | |
| | | private String msg; |
| | | |
| | | private T data; |
| | | |
| | | public static <T> R<T> ok() { |
| | | return restResult(null, SUCCESS, "æä½æå"); |
| | | } |
| | | |
| | | public static <T> R<T> ok(T data) { |
| | | return restResult(data, SUCCESS, "æä½æå"); |
| | | } |
| | | |
| | | public static <T> R<T> ok(String msg) { |
| | | return restResult(null, SUCCESS, msg); |
| | | } |
| | | |
| | | public static <T> R<T> ok(String msg, T data) { |
| | | return restResult(data, SUCCESS, msg); |
| | | } |
| | | |
| | | public static <T> R<T> fail() { |
| | | return restResult(null, FAIL, "æä½å¤±è´¥"); |
| | | } |
| | | |
| | | public static <T> R<T> fail(String msg) { |
| | | return restResult(null, FAIL, msg); |
| | | } |
| | | |
| | | public static <T> R<T> fail(T data) { |
| | | return restResult(data, FAIL, "æä½å¤±è´¥"); |
| | | } |
| | | |
| | | public static <T> R<T> fail(String msg, T data) { |
| | | return restResult(data, FAIL, msg); |
| | | } |
| | | |
| | | public static <T> R<T> fail(int code, String msg) { |
| | | return restResult(null, code, msg); |
| | | } |
| | | |
| | | /** |
| | | * è¿åè¦åæ¶æ¯ |
| | | * |
| | | * @param msg è¿åå
容 |
| | | * @return è¦åæ¶æ¯ |
| | | */ |
| | | public static <T> R<T> warn(String msg) { |
| | | return restResult(null, HttpStatus.WARN, msg); |
| | | } |
| | | |
| | | /** |
| | | * è¿åè¦åæ¶æ¯ |
| | | * |
| | | * @param msg è¿åå
容 |
| | | * @param data æ°æ®å¯¹è±¡ |
| | | * @return è¦åæ¶æ¯ |
| | | */ |
| | | public static <T> R<T> warn(String msg, T data) { |
| | | return restResult(data, HttpStatus.WARN, msg); |
| | | } |
| | | |
| | | private static <T> R<T> restResult(T data, int code, String msg) { |
| | | R<T> r = new R<>(); |
| | | r.setCode(code); |
| | | r.setData(data); |
| | | r.setMsg(msg); |
| | | return r; |
| | | } |
| | | |
| | | public static <T> Boolean isError(R<T> ret) { |
| | | return !isSuccess(ret); |
| | | } |
| | | |
| | | public static <T> Boolean isSuccess(R<T> ret) { |
| | | return R.SUCCESS == ret.getCode(); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.dto; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * åçä»»å¡è¯·æ±å¯¹è±¡ |
| | | * |
| | | * @author may |
| | | */ |
| | | @Data |
| | | public class CompleteTaskDTO implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * ä»»å¡id |
| | | */ |
| | | private Long taskId; |
| | | |
| | | /** |
| | | * éä»¶id |
| | | */ |
| | | private String fileId; |
| | | |
| | | /** |
| | | * æé人å |
| | | */ |
| | | private List<FlowCopyDTO> flowCopyList; |
| | | |
| | | /** |
| | | * æ¶æ¯ç±»å |
| | | */ |
| | | private List<String> messageType; |
| | | |
| | | /** |
| | | * åçæè§ |
| | | */ |
| | | private String message; |
| | | |
| | | /** |
| | | * æ¶æ¯éç¥ |
| | | */ |
| | | private String notice; |
| | | |
| | | /** |
| | | * åç人(å¯ä¸å¡« ç¨äºè¦çå½åèç¹åç人) |
| | | */ |
| | | private String handler; |
| | | |
| | | /** |
| | | * æµç¨åé |
| | | */ |
| | | private Map<String, Object> variables; |
| | | |
| | | /** |
| | | * æ©å±åé(æ¤å¤ä¸ºéå·åéçossId) |
| | | */ |
| | | private String ext; |
| | | |
| | | public Map<String, Object> getVariables() { |
| | | if (variables == null) { |
| | | variables = new HashMap<>(16); |
| | | return variables; |
| | | } |
| | | variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue())); |
| | | return variables; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.dto; |
| | | |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * é¨é¨ |
| | | * |
| | | * @author AprilWind |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | public class DeptDTO implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * é¨é¨ID |
| | | */ |
| | | private Long deptId; |
| | | |
| | | /** |
| | | * ç¶é¨é¨ID |
| | | */ |
| | | private Long parentId; |
| | | |
| | | /** |
| | | * é¨é¨åç§° |
| | | */ |
| | | private String deptName; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.dto; |
| | | |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * åå
¸æ°æ®DTO |
| | | * |
| | | * @author AprilWind |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | public class DictDataDTO implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * åå
¸æ ç¾ |
| | | */ |
| | | private String dictLabel; |
| | | |
| | | /** |
| | | * åå
¸é®å¼ |
| | | */ |
| | | private String dictValue; |
| | | |
| | | /** |
| | | * æ¯å¦é»è®¤ï¼Yæ¯ Nå¦ï¼ |
| | | */ |
| | | private String isDefault; |
| | | |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.dto; |
| | | |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * åå
¸ç±»åDTO |
| | | * |
| | | * @author AprilWind |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | public class DictTypeDTO implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * åå
¸ä¸»é® |
| | | */ |
| | | private Long dictId; |
| | | |
| | | /** |
| | | * åå
¸åç§° |
| | | */ |
| | | private String dictName; |
| | | |
| | | /** |
| | | * åå
¸ç±»å |
| | | */ |
| | | private String dictType; |
| | | |
| | | /** |
| | | * 夿³¨ |
| | | */ |
| | | private String remark; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.dto; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | |
| | | |
| | | /** |
| | | * æé |
| | | * |
| | | * @author may |
| | | */ |
| | | @Data |
| | | public class FlowCopyDTO implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * ç¨æ·id |
| | | */ |
| | | private Long userId; |
| | | |
| | | /** |
| | | * ç¨æ·åç§° |
| | | */ |
| | | private String userName; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.dto; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * æµç¨å®ä¾ä¸å¡æ©å±å¯¹è±¡ |
| | | * |
| | | * @author may |
| | | * @date 2025-08-05 |
| | | */ |
| | | @Data |
| | | public class FlowInstanceBizExtDTO implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * ä¸»é® |
| | | */ |
| | | private Long id; |
| | | |
| | | /** |
| | | * æµç¨å®ä¾ID |
| | | */ |
| | | private Long instanceId; |
| | | |
| | | /** |
| | | * ä¸å¡ID |
| | | */ |
| | | private String businessId; |
| | | |
| | | /** |
| | | * ä¸å¡ç¼ç |
| | | */ |
| | | private String businessCode; |
| | | |
| | | /** |
| | | * ä¸å¡æ é¢ |
| | | */ |
| | | private String businessTitle; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.dto; |
| | | |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * OSS对象 |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | public class OssDTO implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * 对象åå¨ä¸»é® |
| | | */ |
| | | private Long ossId; |
| | | |
| | | /** |
| | | * æä»¶å |
| | | */ |
| | | private String fileName; |
| | | |
| | | /** |
| | | * åå |
| | | */ |
| | | private String originalName; |
| | | |
| | | /** |
| | | * æä»¶åç¼å |
| | | */ |
| | | private String fileSuffix; |
| | | |
| | | /** |
| | | * URLå°å |
| | | */ |
| | | private String url; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.dto; |
| | | |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * å²ä½ |
| | | * |
| | | * @author AprilWind |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | public class PostDTO implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * å²ä½ID |
| | | */ |
| | | private Long postId; |
| | | |
| | | /** |
| | | * é¨é¨id |
| | | */ |
| | | private Long deptId; |
| | | |
| | | /** |
| | | * å²ä½ç¼ç |
| | | */ |
| | | private String postCode; |
| | | |
| | | /** |
| | | * å²ä½åç§° |
| | | */ |
| | | private String postName; |
| | | |
| | | /** |
| | | * å²ä½ç±»å«ç¼ç |
| | | */ |
| | | private String postCategory; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.dto; |
| | | |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * è§è² |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | |
| | | @Data |
| | | @NoArgsConstructor |
| | | public class RoleDTO implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * è§è²ID |
| | | */ |
| | | private Long roleId; |
| | | |
| | | /** |
| | | * è§è²åç§° |
| | | */ |
| | | private String roleName; |
| | | |
| | | /** |
| | | * è§è²æé |
| | | */ |
| | | private String roleKey; |
| | | |
| | | /** |
| | | * æ°æ®èå´ï¼1ï¼å
¨é¨æ°æ®æé 2ï¼èªå®æ°æ®æé 3ï¼æ¬é¨é¨æ°æ®æé 4ï¼æ¬é¨é¨å以䏿°æ®æé 5ï¼ä»
æ¬äººæ°æ®æé 6ï¼é¨é¨å以䏿æ¬äººæ°æ®æéï¼ |
| | | */ |
| | | private String dataScope; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.dto; |
| | | |
| | | |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * å¯å¨æµç¨å¯¹è±¡ |
| | | * |
| | | * @author may |
| | | */ |
| | | @Data |
| | | public class StartProcessDTO implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * ä¸å¡å¯ä¸å¼id |
| | | */ |
| | | private String businessId; |
| | | |
| | | /** |
| | | * æµç¨å®ä¹ç¼ç |
| | | */ |
| | | private String flowCode; |
| | | |
| | | /** |
| | | * åç人(å¯ä¸å¡« ç¨äºè¦çå½åèç¹åç人) |
| | | */ |
| | | private String handler; |
| | | |
| | | /** |
| | | * æµç¨åéï¼åç«¯ä¼æäº¤ä¸ä¸ªå
ç´ {'entity': {ä¸å¡è¯¦æ
æ°æ®å¯¹è±¡}} |
| | | */ |
| | | private Map<String, Object> variables; |
| | | |
| | | /** |
| | | * æµç¨ä¸å¡æ©å±ä¿¡æ¯ |
| | | */ |
| | | private FlowInstanceBizExtDTO bizExt; |
| | | |
| | | public Map<String, Object> getVariables() { |
| | | if (variables == null) { |
| | | return new HashMap<>(16); |
| | | } |
| | | variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue())); |
| | | return variables; |
| | | } |
| | | |
| | | public FlowInstanceBizExtDTO getBizExt() { |
| | | if (ObjectUtil.isNull(bizExt)) { |
| | | bizExt = new FlowInstanceBizExtDTO(); |
| | | } |
| | | return bizExt; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.dto; |
| | | |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * å¯å¨æµç¨è¿å对象 |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Data |
| | | public class StartProcessReturnDTO implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * æµç¨å®ä¾id |
| | | */ |
| | | private Long processInstanceId; |
| | | |
| | | /** |
| | | * ä»»å¡id |
| | | */ |
| | | private Long taskId; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.dto; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.function.Function; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * ä»»å¡å让人 |
| | | * |
| | | * @author AprilWind |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | public class TaskAssigneeDTO implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * æ»å¤§å° |
| | | */ |
| | | private Long total = 0L; |
| | | |
| | | /** |
| | | * |
| | | */ |
| | | private List<TaskHandler> list; |
| | | |
| | | public TaskAssigneeDTO(Long total, List<TaskHandler> list) { |
| | | this.total = total; |
| | | this.list = list; |
| | | } |
| | | |
| | | /** |
| | | * å°æºå表转æ¢ä¸º TaskHandler å表 |
| | | * |
| | | * @param <T> éç¨ç±»å |
| | | * @param sourceList å¾
转æ¢çæºå表 |
| | | * @param storageId æå storageId ç彿° |
| | | * @param handlerCode æå handlerCode ç彿° |
| | | * @param handlerName æå handlerName ç彿° |
| | | * @param groupName æå groupName ç彿° |
| | | * @param createTimeMapper æå createTime ç彿° |
| | | * @return 转æ¢åç TaskHandler å表 |
| | | */ |
| | | public static <T> List<TaskHandler> convertToHandlerList( |
| | | List<T> sourceList, |
| | | Function<T, String> storageId, |
| | | Function<T, String> handlerCode, |
| | | Function<T, String> handlerName, |
| | | Function<T, String> groupName, |
| | | Function<T, Date> createTimeMapper) { |
| | | return sourceList.stream() |
| | | .map(item -> new TaskHandler( |
| | | storageId.apply(item), |
| | | handlerCode.apply(item), |
| | | handlerName.apply(item), |
| | | groupName.apply(item), |
| | | createTimeMapper.apply(item) |
| | | )).collect(Collectors.toList()); |
| | | } |
| | | |
| | | @Data |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public static class TaskHandler { |
| | | |
| | | /** |
| | | * ä¸»é® |
| | | */ |
| | | private String storageId; |
| | | |
| | | /** |
| | | * æéç¼ç |
| | | */ |
| | | private String handlerCode; |
| | | |
| | | /** |
| | | * æéåç§° |
| | | */ |
| | | private String handlerName; |
| | | |
| | | /** |
| | | * æéåç» |
| | | */ |
| | | private String groupName; |
| | | |
| | | /** |
| | | * å建æ¶é´ |
| | | */ |
| | | private Date createTime; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.dto; |
| | | |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | |
| | | |
| | | /** |
| | | * ç¨æ· |
| | | * |
| | | * @author Michelle.Chung |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | public class UserDTO implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * ç¨æ·ID |
| | | */ |
| | | private Long userId; |
| | | |
| | | /** |
| | | * é¨é¨ID |
| | | */ |
| | | private Long deptId; |
| | | |
| | | /** |
| | | * ç¨æ·è´¦å· |
| | | */ |
| | | private String userName; |
| | | |
| | | /** |
| | | * ç¨æ·æµç§° |
| | | */ |
| | | private String nickName; |
| | | |
| | | /** |
| | | * ç¨æ·ç±»åï¼sys_userç³»ç»ç¨æ·ï¼ |
| | | */ |
| | | private String userType; |
| | | |
| | | /** |
| | | * ç¨æ·é®ç®± |
| | | */ |
| | | private String email; |
| | | |
| | | /** |
| | | * ææºå·ç |
| | | */ |
| | | private String phonenumber; |
| | | |
| | | /** |
| | | * ç¨æ·æ§å«ï¼0ç· 1女 2æªç¥ï¼ |
| | | */ |
| | | private String sex; |
| | | |
| | | /** |
| | | * è´¦å·ç¶æï¼0æ£å¸¸ 1åç¨ï¼ |
| | | */ |
| | | private String status; |
| | | |
| | | /** |
| | | * å建æ¶é´ |
| | | */ |
| | | private Date createTime; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.dto; |
| | | |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * å½åå¨çº¿ä¼è¯ |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | |
| | | @Data |
| | | @NoArgsConstructor |
| | | public class UserOnlineDTO implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * ä¼è¯ç¼å· |
| | | */ |
| | | private String tokenId; |
| | | |
| | | /** |
| | | * é¨é¨åç§° |
| | | */ |
| | | private String deptName; |
| | | |
| | | /** |
| | | * ç¨æ·åç§° |
| | | */ |
| | | private String userName; |
| | | |
| | | /** |
| | | * 客æ·ç«¯ |
| | | */ |
| | | private String clientKey; |
| | | |
| | | /** |
| | | * 设å¤ç±»å |
| | | */ |
| | | private String deviceType; |
| | | |
| | | /** |
| | | * ç»å½IPå°å |
| | | */ |
| | | private String ipaddr; |
| | | |
| | | /** |
| | | * ç»å½å°å |
| | | */ |
| | | private String loginLocation; |
| | | |
| | | /** |
| | | * æµè§å¨ç±»å |
| | | */ |
| | | private String browser; |
| | | |
| | | /** |
| | | * æä½ç³»ç» |
| | | */ |
| | | private String os; |
| | | |
| | | /** |
| | | * ç»å½æ¶é´ |
| | | */ |
| | | private Long loginTime; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.event; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * å 餿µç¨çå¬ |
| | | * |
| | | * @author AprilWind |
| | | */ |
| | | @Data |
| | | public class ProcessDeleteEvent implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * ç§æ·ID |
| | | */ |
| | | private String tenantId; |
| | | |
| | | /** |
| | | * æµç¨å®ä¹ç¼ç |
| | | */ |
| | | private String flowCode; |
| | | |
| | | /** |
| | | * ä¸å¡id |
| | | */ |
| | | private String businessId; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.event; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * æ»ä½æµç¨çå¬ |
| | | * |
| | | * @author may |
| | | */ |
| | | @Data |
| | | public class ProcessEvent implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * ç§æ·ID |
| | | */ |
| | | private String tenantId; |
| | | |
| | | /** |
| | | * æµç¨å®ä¹ç¼ç |
| | | */ |
| | | private String flowCode; |
| | | |
| | | /** |
| | | * å®ä¾id |
| | | */ |
| | | private Long instanceId; |
| | | |
| | | /** |
| | | * ä¸å¡id |
| | | */ |
| | | private String businessId; |
| | | |
| | | /** |
| | | * èç¹ç±»åï¼0å¼å§èç¹ 1ä¸é´èç¹ 2ç»æèç¹ 3äºæ¥ç½å
³ 4å¹¶è¡ç½å
³ï¼ |
| | | */ |
| | | private Integer nodeType; |
| | | |
| | | /** |
| | | * æµç¨èç¹ç¼ç |
| | | */ |
| | | private String nodeCode; |
| | | |
| | | /** |
| | | * æµç¨èç¹åç§° |
| | | */ |
| | | private String nodeName; |
| | | |
| | | /** |
| | | * æµç¨ç¶æ |
| | | */ |
| | | private String status; |
| | | |
| | | /** |
| | | * åçåæ° |
| | | */ |
| | | private Map<String, Object> params; |
| | | |
| | | /** |
| | | * å½ä¸ºtrueæ¶ä¸ºç³è¯·äººèç¹åç |
| | | */ |
| | | private Boolean submit; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.event; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * æµç¨ä»»å¡çå¬ |
| | | * |
| | | * @author may |
| | | */ |
| | | @Data |
| | | public class ProcessTaskEvent implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * ç§æ·ID |
| | | */ |
| | | private String tenantId; |
| | | |
| | | /** |
| | | * æµç¨å®ä¹ç¼ç |
| | | */ |
| | | private String flowCode; |
| | | |
| | | /** |
| | | * èç¹ç±»åï¼0å¼å§èç¹ 1ä¸é´èç¹ 2ç»æèç¹ 3äºæ¥ç½å
³ 4å¹¶è¡ç½å
³ï¼ |
| | | */ |
| | | private Integer nodeType; |
| | | |
| | | /** |
| | | * æµç¨èç¹ç¼ç |
| | | */ |
| | | private String nodeCode; |
| | | |
| | | /** |
| | | * æµç¨èç¹åç§° |
| | | */ |
| | | private String nodeName; |
| | | |
| | | /** |
| | | * ä»»å¡id |
| | | */ |
| | | private Long taskId; |
| | | |
| | | /** |
| | | * å®ä¾id |
| | | */ |
| | | private Long instanceId; |
| | | |
| | | /** |
| | | * ä¸å¡id |
| | | */ |
| | | private String businessId; |
| | | |
| | | /** |
| | | * æµç¨ç¶æ |
| | | */ |
| | | private String status; |
| | | |
| | | /** |
| | | * åçåæ° |
| | | */ |
| | | private Map<String, Object> params; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.model; |
| | | |
| | | import jakarta.validation.constraints.Email; |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * é®ä»¶ç»å½å¯¹è±¡ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class EmailLoginBody extends LoginBody { |
| | | |
| | | /** |
| | | * é®ç®± |
| | | */ |
| | | @NotBlank(message = "{user.email.not.blank}") |
| | | @Email(message = "{user.email.not.valid}") |
| | | private String email; |
| | | |
| | | /** |
| | | * é®ç®±code |
| | | */ |
| | | @NotBlank(message = "{email.code.not.blank}") |
| | | private String emailCode; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.model; |
| | | |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * ç¨æ·ç»å½å¯¹è±¡ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | |
| | | @Data |
| | | public class LoginBody implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * 客æ·ç«¯id |
| | | */ |
| | | @NotBlank(message = "{auth.clientid.not.blank}") |
| | | private String clientId; |
| | | |
| | | /** |
| | | * ææç±»å |
| | | */ |
| | | @NotBlank(message = "{auth.grant.type.not.blank}") |
| | | private String grantType; |
| | | |
| | | /** |
| | | * ç§æ·ID |
| | | */ |
| | | private String tenantId; |
| | | |
| | | /** |
| | | * éªè¯ç |
| | | */ |
| | | private String code; |
| | | |
| | | /** |
| | | * å¯ä¸æ è¯ |
| | | */ |
| | | private String uuid; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.model; |
| | | |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | import org.dromara.common.core.domain.dto.PostDTO; |
| | | import org.dromara.common.core.domain.dto.RoleDTO; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * ç»å½ç¨æ·èº«ä»½æé |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | public class LoginUser implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * ç§æ·ID |
| | | */ |
| | | private String tenantId; |
| | | |
| | | /** |
| | | * ç¨æ·ID |
| | | */ |
| | | private Long userId; |
| | | |
| | | /** |
| | | * é¨é¨ID |
| | | */ |
| | | private Long deptId; |
| | | |
| | | /** |
| | | * é¨é¨ç±»å«ç¼ç |
| | | */ |
| | | private String deptCategory; |
| | | |
| | | /** |
| | | * é¨é¨å |
| | | */ |
| | | private String deptName; |
| | | |
| | | /** |
| | | * ç¨æ·å¯ä¸æ è¯ |
| | | */ |
| | | private String token; |
| | | |
| | | /** |
| | | * ç¨æ·ç±»å |
| | | */ |
| | | private String userType; |
| | | |
| | | /** |
| | | * ç»å½æ¶é´ |
| | | */ |
| | | private Long loginTime; |
| | | |
| | | /** |
| | | * è¿ææ¶é´ |
| | | */ |
| | | private Long expireTime; |
| | | |
| | | /** |
| | | * ç»å½IPå°å |
| | | */ |
| | | private String ipaddr; |
| | | |
| | | /** |
| | | * ç»å½å°ç¹ |
| | | */ |
| | | private String loginLocation; |
| | | |
| | | /** |
| | | * æµè§å¨ç±»å |
| | | */ |
| | | private String browser; |
| | | |
| | | /** |
| | | * æä½ç³»ç» |
| | | */ |
| | | private String os; |
| | | |
| | | /** |
| | | * èåæé |
| | | */ |
| | | private Set<String> menuPermission; |
| | | |
| | | /** |
| | | * è§è²æé |
| | | */ |
| | | private Set<String> rolePermission; |
| | | |
| | | /** |
| | | * ç¨æ·å |
| | | */ |
| | | private String username; |
| | | |
| | | /** |
| | | * ç¨æ·æµç§° |
| | | */ |
| | | private String nickname; |
| | | |
| | | /** |
| | | * è§è²å¯¹è±¡ |
| | | */ |
| | | private List<RoleDTO> roles; |
| | | |
| | | /** |
| | | * å²ä½å¯¹è±¡ |
| | | */ |
| | | private List<PostDTO> posts; |
| | | |
| | | /** |
| | | * æ°æ®æé å½åè§è²ID |
| | | */ |
| | | private Long roleId; |
| | | |
| | | /** |
| | | * 客æ·ç«¯ |
| | | */ |
| | | private String clientKey; |
| | | |
| | | /** |
| | | * 设å¤ç±»å |
| | | */ |
| | | private String deviceType; |
| | | |
| | | /** |
| | | * è·åç»å½id |
| | | */ |
| | | public String getLoginId() { |
| | | if (userType == null) { |
| | | throw new IllegalArgumentException("ç¨æ·ç±»åä¸è½ä¸ºç©º"); |
| | | } |
| | | if (userId == null) { |
| | | throw new IllegalArgumentException("ç¨æ·IDä¸è½ä¸ºç©º"); |
| | | } |
| | | return userType + ":" + userId; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.model; |
| | | |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import org.hibernate.validator.constraints.Length; |
| | | |
| | | /** |
| | | * å¯ç ç»å½å¯¹è±¡ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class PasswordLoginBody extends LoginBody { |
| | | |
| | | /** |
| | | * ç¨æ·å |
| | | */ |
| | | @NotBlank(message = "{user.username.not.blank}") |
| | | @Length(min = 2, max = 30, message = "{user.username.length.valid}") |
| | | private String username; |
| | | |
| | | /** |
| | | * ç¨æ·å¯ç |
| | | */ |
| | | @NotBlank(message = "{user.password.not.blank}") |
| | | @Length(min = 5, max = 30, message = "{user.password.length.valid}") |
| | | // @Pattern(regexp = RegexConstants.PASSWORD, message = "{user.password.format.valid}") |
| | | private String password; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.model; |
| | | |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import org.hibernate.validator.constraints.Length; |
| | | |
| | | /** |
| | | * ç¨æ·æ³¨å对象 |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class RegisterBody extends LoginBody { |
| | | |
| | | /** |
| | | * ç¨æ·å |
| | | */ |
| | | @NotBlank(message = "{user.username.not.blank}") |
| | | @Length(min = 2, max = 30, message = "{user.username.length.valid}") |
| | | private String username; |
| | | |
| | | /** |
| | | * ç¨æ·å¯ç |
| | | */ |
| | | @NotBlank(message = "{user.password.not.blank}") |
| | | @Length(min = 5, max = 30, message = "{user.password.length.valid}") |
| | | // @Pattern(regexp = RegexConstants.PASSWORD, message = "{user.password.format.valid}") |
| | | private String password; |
| | | |
| | | /** |
| | | * ç¨æ·ç±»å |
| | | */ |
| | | private String userType; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.model; |
| | | |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * çä¿¡ç»å½å¯¹è±¡ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class SmsLoginBody extends LoginBody { |
| | | |
| | | /** |
| | | * ææºå· |
| | | */ |
| | | @NotBlank(message = "{user.phonenumber.not.blank}") |
| | | private String phonenumber; |
| | | |
| | | /** |
| | | * çä¿¡code |
| | | */ |
| | | @NotBlank(message = "{sms.code.not.blank}") |
| | | private String smsCode; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.model; |
| | | |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * 䏿¹ç»å½å¯¹è±¡ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class SocialLoginBody extends LoginBody { |
| | | |
| | | /** |
| | | * ç¬¬ä¸æ¹ç»å½å¹³å° |
| | | */ |
| | | @NotBlank(message = "{social.source.not.blank}") |
| | | private String source; |
| | | |
| | | /** |
| | | * ç¬¬ä¸æ¹ç»å½code |
| | | */ |
| | | @NotBlank(message = "{social.code.not.blank}") |
| | | private String socialCode; |
| | | |
| | | /** |
| | | * ç¬¬ä¸æ¹ç»å½socialState |
| | | */ |
| | | @NotBlank(message = "{social.state.not.blank}") |
| | | private String socialState; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.model; |
| | | |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * ä»»å¡å让人 |
| | | * |
| | | * @author AprilWind |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | public class TaskAssigneeBody implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * æéç¼ç |
| | | */ |
| | | private String handlerCode; |
| | | |
| | | /** |
| | | * æéåç§° |
| | | */ |
| | | private String handlerName; |
| | | |
| | | /** |
| | | * æéåç» |
| | | */ |
| | | private String groupId; |
| | | |
| | | /** |
| | | * å¼å§æ¶é´ |
| | | */ |
| | | private String beginTime; |
| | | |
| | | /** |
| | | * ç»ææ¶é´ |
| | | */ |
| | | private String endTime; |
| | | |
| | | /** |
| | | * å½å页 |
| | | */ |
| | | private Integer pageNum = 1; |
| | | |
| | | /** |
| | | * æ¯é¡µæ¾ç¤ºæ¡æ° |
| | | */ |
| | | private Integer pageSize = 10; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.model; |
| | | |
| | | import jakarta.validation.constraints.NotBlank; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * 䏿¹ç»å½å¯¹è±¡ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | public class XcxLoginBody extends LoginBody { |
| | | |
| | | /** |
| | | * å°ç¨åºid(å¤ä¸ªå°ç¨åºæ¶ä½¿ç¨) |
| | | */ |
| | | private String appid; |
| | | |
| | | /** |
| | | * å°ç¨åºcode |
| | | */ |
| | | @NotBlank(message = "{xcx.code.not.blank}") |
| | | private String xcxCode; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.domain.model; |
| | | |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serial; |
| | | |
| | | /** |
| | | * å°ç¨åºç»å½ç¨æ·èº«ä»½æé |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @NoArgsConstructor |
| | | public class XcxLoginUser extends LoginUser { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * openid |
| | | */ |
| | | private String openid; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.enums; |
| | | |
| | | import cn.hutool.core.util.StrUtil; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.function.Function; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * ä¸å¡ç¶ææä¸¾ |
| | | * |
| | | * @author may |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum BusinessStatusEnum { |
| | | |
| | | /** |
| | | * å·²æ¤é |
| | | */ |
| | | CANCEL("cancel", "å·²æ¤é"), |
| | | |
| | | /** |
| | | * è稿 |
| | | */ |
| | | DRAFT("draft", "è稿"), |
| | | |
| | | /** |
| | | * å¾
å®¡æ ¸ |
| | | */ |
| | | WAITING("waiting", "å¾
å®¡æ ¸"), |
| | | |
| | | /** |
| | | * 已宿 |
| | | */ |
| | | FINISH("finish", "已宿"), |
| | | |
| | | /** |
| | | * å·²ä½åº |
| | | */ |
| | | INVALID("invalid", "å·²ä½åº"), |
| | | |
| | | /** |
| | | * å·²éå |
| | | */ |
| | | BACK("back", "å·²éå"), |
| | | |
| | | /** |
| | | * å·²ç»æ¢ |
| | | */ |
| | | TERMINATION("termination", "å·²ç»æ¢"); |
| | | |
| | | /** |
| | | * ç¶æ |
| | | */ |
| | | private final String status; |
| | | |
| | | /** |
| | | * æè¿° |
| | | */ |
| | | private final String desc; |
| | | |
| | | private static final Map<String, BusinessStatusEnum> STATUS_MAP = Arrays.stream(BusinessStatusEnum.values()) |
| | | .collect(Collectors.toConcurrentMap(BusinessStatusEnum::getStatus, Function.identity())); |
| | | |
| | | /** |
| | | * æ ¹æ®ç¶æè·å对åºç BusinessStatusEnum æä¸¾ |
| | | * |
| | | * @param status ä¸å¡ç¶æç |
| | | * @return 对åºç BusinessStatusEnum æä¸¾ï¼å¦ææ¾ä¸å°åè¿å null |
| | | */ |
| | | public static BusinessStatusEnum getByStatus(String status) { |
| | | // ä½¿ç¨ STATUS_MAP è·å对åºçæä¸¾ï¼è¥æ¾ä¸å°åè¿å null |
| | | return STATUS_MAP.get(status); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®ç¶æè·å对åºçä¸å¡ç¶ææè¿°ä¿¡æ¯ |
| | | * |
| | | * @param status ä¸å¡ç¶æç |
| | | * @return è¿åä¸å¡ç¶ææè¿°ï¼è¥ç¶æç ä¸ºç©ºææªæ¾å°å¯¹åºçæä¸¾ï¼è¿å空å符串 |
| | | */ |
| | | public static String findByStatus(String status) { |
| | | if (StringUtils.isBlank(status)) { |
| | | return StrUtil.EMPTY; |
| | | } |
| | | BusinessStatusEnum statusEnum = STATUS_MAP.get(status); |
| | | return (statusEnum != null) ? statusEnum.getDesc() : StrUtil.EMPTY; |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦ä¸ºæå®çç¶æä¹ä¸ï¼è稿ãå·²æ¤éæå·²éå |
| | | * |
| | | * @param status è¦æ£æ¥çç¶æ |
| | | * @return å¦æç¶æä¸ºè稿ãå·²æ¤éæå·²éåä¹ä¸ï¼åè¿å trueï¼å¦åè¿å false |
| | | */ |
| | | public static boolean isDraftOrCancelOrBack(String status) { |
| | | return DRAFT.status.equals(status) || CANCEL.status.equals(status) || BACK.status.equals(status); |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦ä¸ºæ¤éï¼éåï¼ä½åºï¼ç»æ¢ |
| | | * |
| | | * @param status status |
| | | * @return ç»æ |
| | | */ |
| | | public static boolean initialState(String status) { |
| | | return CANCEL.status.equals(status) || BACK.status.equals(status) || INVALID.status.equals(status) || TERMINATION.status.equals(status); |
| | | } |
| | | |
| | | /** |
| | | * è·åè¿è¡ä¸çå®ä¾ç¶æå表 |
| | | * |
| | | * @return å
å«è¿è¡ä¸å®ä¾ç¶æçä¸å¯åå表 |
| | | * ï¼å
å« DRAFTãWAITINGãBACK å CANCEL ç¶æï¼ |
| | | */ |
| | | public static List<String> runningStatus() { |
| | | return Arrays.asList(DRAFT.status, WAITING.status, BACK.status, CANCEL.status); |
| | | } |
| | | |
| | | /** |
| | | * è·åç»æå®ä¾çç¶æå表 |
| | | * |
| | | * @return å
å«ç»æå®ä¾ç¶æçä¸å¯åå表 |
| | | * ï¼å
å« FINISHãINVALID å TERMINATION ç¶æï¼ |
| | | */ |
| | | public static List<String> finishStatus() { |
| | | return Arrays.asList(FINISH.status, INVALID.status, TERMINATION.status); |
| | | } |
| | | |
| | | /** |
| | | * å¯å¨æµç¨æ ¡éª |
| | | * |
| | | * @param status ç¶æ |
| | | */ |
| | | public static void checkStartStatus(String status) { |
| | | if (WAITING.getStatus().equals(status)) { |
| | | throw new ServiceException("è¯¥åæ®å·²æäº¤è¿ç³è¯·,æ£å¨å®¡æ¹ä¸ï¼"); |
| | | } else if (FINISH.getStatus().equals(status)) { |
| | | throw new ServiceException("è¯¥åæ®å·²å®æç³è¯·ï¼"); |
| | | } else if (INVALID.getStatus().equals(status)) { |
| | | throw new ServiceException("è¯¥åæ®å·²ä½åºï¼"); |
| | | } else if (TERMINATION.getStatus().equals(status)) { |
| | | throw new ServiceException("è¯¥åæ®å·²ç»æ¢ï¼"); |
| | | } else if (StringUtils.isBlank(status)) { |
| | | throw new ServiceException("æµç¨ç¶æä¸ºç©ºï¼"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ¤éæµç¨æ ¡éª |
| | | * |
| | | * @param status ç¶æ |
| | | */ |
| | | public static void checkCancelStatus(String status) { |
| | | if (CANCEL.getStatus().equals(status)) { |
| | | throw new ServiceException("è¯¥åæ®å·²æ¤éï¼"); |
| | | } else if (FINISH.getStatus().equals(status)) { |
| | | throw new ServiceException("è¯¥åæ®å·²å®æç³è¯·ï¼"); |
| | | } else if (INVALID.getStatus().equals(status)) { |
| | | throw new ServiceException("è¯¥åæ®å·²ä½åºï¼"); |
| | | } else if (TERMINATION.getStatus().equals(status)) { |
| | | throw new ServiceException("è¯¥åæ®å·²ç»æ¢ï¼"); |
| | | } else if (BACK.getStatus().equals(status)) { |
| | | throw new ServiceException("è¯¥åæ®å·²éåï¼"); |
| | | } else if (StringUtils.isBlank(status)) { |
| | | throw new ServiceException("æµç¨ç¶æä¸ºç©ºï¼"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * é©³åæµç¨æ ¡éª |
| | | * |
| | | * @param status ç¶æ |
| | | */ |
| | | public static void checkBackStatus(String status) { |
| | | if (BACK.getStatus().equals(status)) { |
| | | throw new ServiceException("è¯¥åæ®å·²éåï¼"); |
| | | } else if (FINISH.getStatus().equals(status)) { |
| | | throw new ServiceException("è¯¥åæ®å·²å®æç³è¯·ï¼"); |
| | | } else if (INVALID.getStatus().equals(status)) { |
| | | throw new ServiceException("è¯¥åæ®å·²ä½åºï¼"); |
| | | } else if (TERMINATION.getStatus().equals(status)) { |
| | | throw new ServiceException("è¯¥åæ®å·²ç»æ¢ï¼"); |
| | | } else if (CANCEL.getStatus().equals(status)) { |
| | | throw new ServiceException("è¯¥åæ®å·²æ¤éï¼"); |
| | | } else if (StringUtils.isBlank(status)) { |
| | | throw new ServiceException("æµç¨ç¶æä¸ºç©ºï¼"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * ä½åº,ç»æ¢æµç¨æ ¡éª |
| | | * |
| | | * @param status ç¶æ |
| | | */ |
| | | public static void checkInvalidStatus(String status) { |
| | | if (FINISH.getStatus().equals(status)) { |
| | | throw new ServiceException("è¯¥åæ®å·²å®æç³è¯·ï¼"); |
| | | } else if (INVALID.getStatus().equals(status)) { |
| | | throw new ServiceException("è¯¥åæ®å·²ä½åºï¼"); |
| | | } else if (TERMINATION.getStatus().equals(status)) { |
| | | throw new ServiceException("è¯¥åæ®å·²ç»æ¢ï¼"); |
| | | } else if (StringUtils.isBlank(status)) { |
| | | throw new ServiceException("æµç¨ç¶æä¸ºç©ºï¼"); |
| | | } |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.enums; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | /** |
| | | * 设å¤ç±»å |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum DeviceType { |
| | | |
| | | /** |
| | | * pc端 |
| | | */ |
| | | PC("pc"), |
| | | |
| | | /** |
| | | * app端 |
| | | */ |
| | | APP("app"), |
| | | |
| | | /** |
| | | * å°ç¨åºç«¯ |
| | | */ |
| | | XCX("xcx"), |
| | | |
| | | /** |
| | | * ç¬¬ä¸æ¹ç¤¾äº¤ç»å½å¹³å° |
| | | */ |
| | | SOCIAL("social"); |
| | | |
| | | /** |
| | | * è®¾å¤æ è¯ |
| | | */ |
| | | private final String device; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.enums; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | |
| | | /* |
| | | * æ¥ææ ¼å¼ |
| | | * "yyyy"ï¼4使°ç年份ï¼ä¾å¦ï¼2023年表示为"2023"ã |
| | | * "yy"ï¼2使°ç年份ï¼ä¾å¦ï¼2023年表示为"23"ã |
| | | * "MM"ï¼2使°çæä»½ï¼åå¼èå´ä¸º01å°12ï¼ä¾å¦ï¼7æè¡¨ç¤ºä¸º"07"ã |
| | | * "M"ï¼ä¸å¸¦å导é¶çæä»½ï¼åå¼èå´ä¸º1å°12ï¼ä¾å¦ï¼7æè¡¨ç¤ºä¸º"7"ã |
| | | * "dd"ï¼2使°çæ¥æï¼åå¼èå´ä¸º01å°31ï¼ä¾å¦ï¼22æ¥è¡¨ç¤ºä¸º"22"ã |
| | | * "d"ï¼ä¸å¸¦å导é¶çæ¥æï¼åå¼èå´ä¸º1å°31ï¼ä¾å¦ï¼22æ¥è¡¨ç¤ºä¸º"22"ã |
| | | * "EEEE"ï¼ææçå
¨åï¼ä¾å¦ï¼ææä¸è¡¨ç¤ºä¸º"Wednesday"ã |
| | | * "E"ï¼ææç缩åï¼ä¾å¦ï¼ææä¸è¡¨ç¤ºä¸º"Wed"ã |
| | | * "DDD" æ "D"ï¼ä¸å¹´ä¸ç第å 天ï¼åå¼èå´ä¸º001å°366ï¼ä¾å¦ï¼ç¬¬200天表示为"200"ã |
| | | * æ¶é´æ ¼å¼ |
| | | * "HH"ï¼24å°æ¶å¶çå°æ¶æ°ï¼åå¼èå´ä¸º00å°23ï¼ä¾å¦ï¼ä¸å5ç¹è¡¨ç¤ºä¸º"17"ã |
| | | * "hh"ï¼12å°æ¶å¶çå°æ¶æ°ï¼åå¼èå´ä¸º01å°12ï¼ä¾å¦ï¼ä¸å5ç¹è¡¨ç¤ºä¸º"05"ã |
| | | * "mm"ï¼åéæ°ï¼åå¼èå´ä¸º00å°59ï¼ä¾å¦ï¼30åé表示为"30"ã |
| | | * "ss"ï¼ç§æ°ï¼åå¼èå´ä¸º00å°59ï¼ä¾å¦ï¼45ç§è¡¨ç¤ºä¸º"45"ã |
| | | * "SSS"ï¼æ¯«ç§æ°ï¼åå¼èå´ä¸º000å°999ï¼ä¾å¦ï¼123毫ç§è¡¨ç¤ºä¸º"123"ã |
| | | */ |
| | | |
| | | /** |
| | | * æ¥ææ ¼å¼ä¸æ¶é´æ ¼å¼æä¸¾ |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum FormatsType { |
| | | |
| | | /** |
| | | * ä¾å¦ï¼2023年表示为"23" |
| | | */ |
| | | YY("yy"), |
| | | |
| | | /** |
| | | * ä¾å¦ï¼2023年表示为"2023" |
| | | */ |
| | | YYYY("yyyy"), |
| | | |
| | | /** |
| | | * ä¾ä¾å¦ï¼2023å¹´7æå¯ä»¥è¡¨ç¤ºä¸º "2023-07" |
| | | */ |
| | | YYYY_MM("yyyy-MM"), |
| | | |
| | | /** |
| | | * ä¾å¦ï¼æ¥æ "2023å¹´7æ22æ¥" å¯ä»¥è¡¨ç¤ºä¸º "2023-07-22" |
| | | */ |
| | | YYYY_MM_DD("yyyy-MM-dd"), |
| | | |
| | | /** |
| | | * ä¾å¦ï¼å½åæ¶é´å¦ææ¯ "2023å¹´7æ22æ¥ä¸å3ç¹30å"ï¼åå¯ä»¥è¡¨ç¤ºä¸º "2023-07-22 15:30" |
| | | */ |
| | | YYYY_MM_DD_HH_MM("yyyy-MM-dd HH:mm"), |
| | | |
| | | /** |
| | | * ä¾å¦ï¼å½åæ¶é´å¦ææ¯ "2023å¹´7æ22æ¥ä¸å3ç¹30å45ç§"ï¼åå¯ä»¥è¡¨ç¤ºä¸º "2023-07-22 15:30:45" |
| | | */ |
| | | YYYY_MM_DD_HH_MM_SS("yyyy-MM-dd HH:mm:ss"), |
| | | |
| | | /** |
| | | * ä¾å¦ï¼ä¸å3ç¹30å45ç§ï¼è¡¨ç¤ºä¸º "15:30:45" |
| | | */ |
| | | HH_MM_SS("HH:mm:ss"), |
| | | |
| | | /** |
| | | * ä¾ä¾å¦ï¼2023å¹´7æå¯ä»¥è¡¨ç¤ºä¸º "2023/07" |
| | | */ |
| | | YYYY_MM_SLASH("yyyy/MM"), |
| | | |
| | | /** |
| | | * ä¾å¦ï¼æ¥æ "2023å¹´7æ22æ¥" å¯ä»¥è¡¨ç¤ºä¸º "2023/07/22" |
| | | */ |
| | | YYYY_MM_DD_SLASH("yyyy/MM/dd"), |
| | | |
| | | /** |
| | | * ä¾å¦ï¼å½åæ¶é´å¦ææ¯ "2023å¹´7æ22æ¥ä¸å3ç¹30å45ç§"ï¼åå¯ä»¥è¡¨ç¤ºä¸º "2023/07/22 15:30:45" |
| | | */ |
| | | YYYY_MM_DD_HH_MM_SLASH("yyyy/MM/dd HH:mm"), |
| | | |
| | | /** |
| | | * ä¾å¦ï¼å½åæ¶é´å¦ææ¯ "2023å¹´7æ22æ¥ä¸å3ç¹30å45ç§"ï¼åå¯ä»¥è¡¨ç¤ºä¸º "2023/07/22 15:30:45" |
| | | */ |
| | | YYYY_MM_DD_HH_MM_SS_SLASH("yyyy/MM/dd HH:mm:ss"), |
| | | |
| | | /** |
| | | * ä¾ä¾å¦ï¼2023å¹´7æå¯ä»¥è¡¨ç¤ºä¸º "2023.07" |
| | | */ |
| | | YYYY_MM_DOT("yyyy.MM"), |
| | | |
| | | /** |
| | | * ä¾å¦ï¼æ¥æ "2023å¹´7æ22æ¥" å¯ä»¥è¡¨ç¤ºä¸º "2023.07.22" |
| | | */ |
| | | YYYY_MM_DD_DOT("yyyy.MM.dd"), |
| | | |
| | | /** |
| | | * ä¾å¦ï¼å½åæ¶é´å¦ææ¯ "2023å¹´7æ22æ¥ä¸å3ç¹30å"ï¼åå¯ä»¥è¡¨ç¤ºä¸º "2023.07.22 15:30" |
| | | */ |
| | | YYYY_MM_DD_HH_MM_DOT("yyyy.MM.dd HH:mm"), |
| | | |
| | | /** |
| | | * ä¾å¦ï¼å½åæ¶é´å¦ææ¯ "2023å¹´7æ22æ¥ä¸å3ç¹30å45ç§"ï¼åå¯ä»¥è¡¨ç¤ºä¸º "2023.07.22 15:30:45" |
| | | */ |
| | | YYYY_MM_DD_HH_MM_SS_DOT("yyyy.MM.dd HH:mm:ss"), |
| | | |
| | | /** |
| | | * ä¾å¦ï¼2023å¹´7æå¯ä»¥è¡¨ç¤ºä¸º "202307" |
| | | */ |
| | | YYYYMM("yyyyMM"), |
| | | |
| | | /** |
| | | * ä¾å¦ï¼2023å¹´7æ22æ¥å¯ä»¥è¡¨ç¤ºä¸º "20230722" |
| | | */ |
| | | YYYYMMDD("yyyyMMdd"), |
| | | |
| | | /** |
| | | * ä¾å¦ï¼2023å¹´7æ22æ¥ä¸å3ç¹å¯ä»¥è¡¨ç¤ºä¸º "2023072215" |
| | | */ |
| | | YYYYMMDDHH("yyyyMMddHH"), |
| | | |
| | | /** |
| | | * ä¾å¦ï¼2023å¹´7æ22æ¥ä¸å3ç¹30åå¯ä»¥è¡¨ç¤ºä¸º "202307221530" |
| | | */ |
| | | YYYYMMDDHHMM("yyyyMMddHHmm"), |
| | | |
| | | /** |
| | | * ä¾å¦ï¼2023å¹´7æ22æ¥ä¸å3ç¹30å45ç§å¯ä»¥è¡¨ç¤ºä¸º "20230722153045" |
| | | */ |
| | | YYYYMMDDHHMMSS("yyyyMMddHHmmss"); |
| | | |
| | | /** |
| | | * æ¶é´æ ¼å¼ |
| | | */ |
| | | private final String timeFormat; |
| | | |
| | | public static FormatsType getFormatsType(String str) { |
| | | for (FormatsType value : values()) { |
| | | if (StringUtils.contains(str, value.getTimeFormat())) { |
| | | return value; |
| | | } |
| | | } |
| | | throw new RuntimeException("'FormatsType' not found By " + str); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.enums; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | /** |
| | | * ç»å½ç±»å |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum LoginType { |
| | | |
| | | /** |
| | | * å¯ç ç»å½ |
| | | */ |
| | | PASSWORD("user.password.retry.limit.exceed", "user.password.retry.limit.count"), |
| | | |
| | | /** |
| | | * çä¿¡ç»å½ |
| | | */ |
| | | SMS("sms.code.retry.limit.exceed", "sms.code.retry.limit.count"), |
| | | |
| | | /** |
| | | * é®ç®±ç»å½ |
| | | */ |
| | | EMAIL("email.code.retry.limit.exceed", "email.code.retry.limit.count"), |
| | | |
| | | /** |
| | | * å°ç¨åºç»å½ |
| | | */ |
| | | XCX("", ""); |
| | | |
| | | /** |
| | | * ç»å½éè¯è¶
åºéå¶æç¤º |
| | | */ |
| | | final String retryLimitExceed; |
| | | |
| | | /** |
| | | * ç»å½éè¯éå¶è®¡æ°æç¤º |
| | | */ |
| | | final String retryLimitCount; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.enums; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | /** |
| | | * ç¨æ·ç¶æ |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum UserStatus { |
| | | /** |
| | | * æ£å¸¸ |
| | | */ |
| | | OK("0", "æ£å¸¸"), |
| | | /** |
| | | * åç¨ |
| | | */ |
| | | DISABLE("1", "åç¨"), |
| | | /** |
| | | * å é¤ |
| | | */ |
| | | DELETED("2", "å é¤"); |
| | | |
| | | private final String code; |
| | | private final String info; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.enums; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | |
| | | /** |
| | | * ç¨æ·ç±»å |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum UserType { |
| | | |
| | | /** |
| | | * åå°ç³»ç»ç¨æ· |
| | | */ |
| | | SYS_USER("sys_user"), |
| | | |
| | | /** |
| | | * ç§»å¨å®¢æ·ç«¯ç¨æ· |
| | | */ |
| | | APP_USER("app_user"); |
| | | |
| | | /** |
| | | * ç¨æ·ç±»åæ è¯ï¼ç¨äº tokenãæéè¯å«çï¼ |
| | | */ |
| | | private final String userType; |
| | | |
| | | public static UserType getUserType(String str) { |
| | | for (UserType value : values()) { |
| | | if (StringUtils.contains(str, value.getUserType())) { |
| | | return value; |
| | | } |
| | | } |
| | | throw new RuntimeException("'UserType' not found By " + str); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.exception; |
| | | |
| | | import cn.hutool.core.text.StrFormatter; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serial; |
| | | |
| | | /** |
| | | * ä¸å¡å¼å¸¸ï¼æ¯æå ä½ç¬¦ {} ï¼ |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public final class ServiceException extends RuntimeException { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * é误ç |
| | | */ |
| | | private Integer code; |
| | | |
| | | /** |
| | | * é误æç¤º |
| | | */ |
| | | private String message; |
| | | |
| | | /** |
| | | * é误æç»ï¼å
é¨è°è¯é误 |
| | | */ |
| | | private String detailMessage; |
| | | |
| | | public ServiceException(String message) { |
| | | this.message = message; |
| | | } |
| | | |
| | | public ServiceException(String message, Integer code) { |
| | | this.message = message; |
| | | this.code = code; |
| | | } |
| | | |
| | | public ServiceException(String message, Object... args) { |
| | | this.message = StrFormatter.format(message, args); |
| | | } |
| | | |
| | | @Override |
| | | public String getMessage() { |
| | | return message; |
| | | } |
| | | |
| | | public ServiceException setMessage(String message) { |
| | | this.message = message; |
| | | return this; |
| | | } |
| | | |
| | | public ServiceException setDetailMessage(String detailMessage) { |
| | | this.detailMessage = detailMessage; |
| | | return this; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.exception; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serial; |
| | | |
| | | /** |
| | | * sse ç¹å¶å¼å¸¸ |
| | | * |
| | | * @author LionLi |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public final class SseException extends RuntimeException { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * é误ç |
| | | */ |
| | | private Integer code; |
| | | |
| | | /** |
| | | * é误æç¤º |
| | | */ |
| | | private String message; |
| | | |
| | | /** |
| | | * é误æç»ï¼å
é¨è°è¯é误 |
| | | */ |
| | | private String detailMessage; |
| | | |
| | | public SseException(String message) { |
| | | this.message = message; |
| | | } |
| | | |
| | | public SseException(String message, Integer code) { |
| | | this.message = message; |
| | | this.code = code; |
| | | } |
| | | |
| | | @Override |
| | | public String getMessage() { |
| | | return message; |
| | | } |
| | | |
| | | public SseException setMessage(String message) { |
| | | this.message = message; |
| | | return this; |
| | | } |
| | | |
| | | public SseException setDetailMessage(String detailMessage) { |
| | | this.detailMessage = detailMessage; |
| | | return this; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.exception.base; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import org.dromara.common.core.utils.MessageUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serial; |
| | | |
| | | /** |
| | | * åºç¡å¼å¸¸ |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @NoArgsConstructor |
| | | @AllArgsConstructor |
| | | public class BaseException extends RuntimeException { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * æå±æ¨¡å |
| | | */ |
| | | private String module; |
| | | |
| | | /** |
| | | * é误ç |
| | | */ |
| | | private String code; |
| | | |
| | | /** |
| | | * é误ç 对åºçåæ° |
| | | */ |
| | | private Object[] args; |
| | | |
| | | /** |
| | | * éè¯¯æ¶æ¯ |
| | | */ |
| | | private String defaultMessage; |
| | | |
| | | public BaseException(String module, String code, Object[] args) { |
| | | this(module, code, args, null); |
| | | } |
| | | |
| | | public BaseException(String module, String defaultMessage) { |
| | | this(module, null, null, defaultMessage); |
| | | } |
| | | |
| | | public BaseException(String code, Object[] args) { |
| | | this(null, code, args, null); |
| | | } |
| | | |
| | | public BaseException(String defaultMessage) { |
| | | this(null, null, null, defaultMessage); |
| | | } |
| | | |
| | | @Override |
| | | public String getMessage() { |
| | | String message = null; |
| | | if (!StringUtils.isEmpty(code)) { |
| | | message = MessageUtils.message(code, args); |
| | | } |
| | | if (message == null) { |
| | | message = defaultMessage; |
| | | } |
| | | return message; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.exception.file; |
| | | |
| | | import org.dromara.common.core.exception.base.BaseException; |
| | | |
| | | import java.io.Serial; |
| | | |
| | | /** |
| | | * æä»¶ä¿¡æ¯å¼å¸¸ç±» |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | public class FileException extends BaseException { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | public FileException(String code, Object[] args) { |
| | | super("file", code, args, null); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.exception.file; |
| | | |
| | | import java.io.Serial; |
| | | |
| | | /** |
| | | * æä»¶åç§°è¶
é¿éå¶å¼å¸¸ç±» |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | public class FileNameLengthLimitExceededException extends FileException { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | public FileNameLengthLimitExceededException(int defaultFileNameLength) { |
| | | super("upload.filename.exceed.length", new Object[]{defaultFileNameLength}); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.exception.file; |
| | | |
| | | import java.io.Serial; |
| | | |
| | | /** |
| | | * æä»¶å大å°éå¶å¼å¸¸ç±» |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | public class FileSizeLimitExceededException extends FileException { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | public FileSizeLimitExceededException(long defaultMaxSize) { |
| | | super("upload.exceed.maxSize", new Object[]{defaultMaxSize}); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.exception.user; |
| | | |
| | | import java.io.Serial; |
| | | |
| | | /** |
| | | * éªè¯ç é误å¼å¸¸ç±» |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | public class CaptchaException extends UserException { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | public CaptchaException() { |
| | | super("user.jcaptcha.error"); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.exception.user; |
| | | |
| | | import java.io.Serial; |
| | | |
| | | /** |
| | | * éªè¯ç 失æå¼å¸¸ç±» |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | public class CaptchaExpireException extends UserException { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | public CaptchaExpireException() { |
| | | super("user.jcaptcha.expire"); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.exception.user; |
| | | |
| | | import org.dromara.common.core.exception.base.BaseException; |
| | | |
| | | import java.io.Serial; |
| | | |
| | | /** |
| | | * ç¨æ·ä¿¡æ¯å¼å¸¸ç±» |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | public class UserException extends BaseException { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | public UserException(String code, Object... args) { |
| | | super("user", code, args, null); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.factory; |
| | | |
| | | import cn.hutool.core.lang.PatternPool; |
| | | import org.dromara.common.core.constant.RegexConstants; |
| | | |
| | | import java.util.regex.Pattern; |
| | | |
| | | /** |
| | | * æ£åè¡¨è¾¾å¼æ¨¡å¼æ± å·¥å |
| | | * <p>åå§åçæ¶åå°æ£å表达å¼å å
¥ç¼åæ± å½ä¸</p> |
| | | * <p>æé«æ£å表达å¼çæ§è½ï¼é¿å
éå¤ç¼è¯ç¸åçæ£å表达å¼</p> |
| | | * |
| | | * @author 21001 |
| | | */ |
| | | public class RegexPatternPoolFactory extends PatternPool { |
| | | |
| | | /** |
| | | * åå
¸ç±»åå¿
须以忝å¼å¤´ï¼ä¸åªè½ä¸ºï¼å°ååæ¯ï¼æ°åï¼ä¸æ»çº¿ï¼ |
| | | */ |
| | | public static final Pattern DICTIONARY_TYPE = get(RegexConstants.DICTIONARY_TYPE); |
| | | |
| | | /** |
| | | * 身份è¯å·ç ï¼å6ä½ï¼ |
| | | */ |
| | | public static final Pattern ID_CARD_LAST_6 = get(RegexConstants.ID_CARD_LAST_6); |
| | | |
| | | /** |
| | | * QQå·ç |
| | | */ |
| | | public static final Pattern QQ_NUMBER = get(RegexConstants.QQ_NUMBER); |
| | | |
| | | /** |
| | | * 鮿¿ç¼ç |
| | | */ |
| | | public static final Pattern POSTAL_CODE = get(RegexConstants.POSTAL_CODE); |
| | | |
| | | /** |
| | | * 注åè´¦å· |
| | | */ |
| | | public static final Pattern ACCOUNT = get(RegexConstants.ACCOUNT); |
| | | |
| | | /** |
| | | * å¯ç ï¼å
å«è³å°8个å符ï¼å
æ¬å¤§å忝ãå°ååæ¯ãæ°ååç¹æ®å符 |
| | | */ |
| | | public static final Pattern PASSWORD = get(RegexConstants.PASSWORD); |
| | | |
| | | /** |
| | | * éç¨ç¶æï¼0表示æ£å¸¸ï¼1表示åç¨ï¼ |
| | | */ |
| | | public static final Pattern STATUS = get(RegexConstants.STATUS); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.factory; |
| | | |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.springframework.beans.factory.config.YamlPropertiesFactoryBean; |
| | | import org.springframework.core.env.PropertiesPropertySource; |
| | | import org.springframework.core.env.PropertySource; |
| | | import org.springframework.core.io.support.DefaultPropertySourceFactory; |
| | | import org.springframework.core.io.support.EncodedResource; |
| | | |
| | | import java.io.IOException; |
| | | |
| | | /** |
| | | * yml é
ç½®æºå·¥å |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public class YmlPropertySourceFactory extends DefaultPropertySourceFactory { |
| | | |
| | | @Override |
| | | public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException { |
| | | String sourceName = resource.getResource().getFilename(); |
| | | if (StringUtils.isNotBlank(sourceName) && StringUtils.endsWithAny(sourceName, ".yml", ".yaml")) { |
| | | YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean(); |
| | | factory.setResources(resource.getResource()); |
| | | factory.afterPropertiesSet(); |
| | | return new PropertiesPropertySource(sourceName, factory.getObject()); |
| | | } |
| | | return super.createPropertySource(name, resource); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.service; |
| | | |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.lang.Dict; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * éç¨ åæ°é
ç½®æå¡ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public interface ConfigService { |
| | | |
| | | /** |
| | | * æ ¹æ®åæ° key è·ååæ°å¼ |
| | | * |
| | | * @param configKey åæ° key |
| | | * @return åæ°å¼ |
| | | */ |
| | | String getConfigValue(String configKey); |
| | | |
| | | /** |
| | | * æ ¹æ®åæ° key è·åå¸å°å¼ |
| | | * |
| | | * @param configKey åæ° key |
| | | * @return Boolean å¼ |
| | | */ |
| | | default Boolean getConfigBool(String configKey) { |
| | | return Convert.toBool(getConfigValue(configKey)); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®åæ° key è·åæ´æ°å¼ |
| | | * |
| | | * @param configKey åæ° key |
| | | * @return Integer å¼ |
| | | */ |
| | | default Integer getConfigInt(String configKey) { |
| | | return Convert.toInt(getConfigValue(configKey)); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®åæ° key è·åé¿æ´åå¼ |
| | | * |
| | | * @param configKey åæ° key |
| | | * @return Long å¼ |
| | | */ |
| | | default Long getConfigLong(String configKey) { |
| | | return Convert.toLong(getConfigValue(configKey)); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®åæ° key è·å BigDecimal å¼ |
| | | * |
| | | * @param configKey åæ° key |
| | | * @return BigDecimal å¼ |
| | | */ |
| | | default BigDecimal getConfigDecimal(String configKey) { |
| | | return Convert.toBigDecimal(getConfigValue(configKey)); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®åæ° key è·å Map ç±»åçé
ç½® |
| | | * |
| | | * @param configKey åæ° key |
| | | * @return Dict 对象ï¼å¦æé
ç½®ä¸ºç©ºææ æ³è§£æï¼è¿å空 Dict |
| | | */ |
| | | Dict getConfigMap(String configKey); |
| | | |
| | | /** |
| | | * æ ¹æ®åæ° key è·å Map ç±»åçé
ç½®å表 |
| | | * |
| | | * @param configKey åæ° key |
| | | * @return Dict å表ï¼å¦æé
ç½®ä¸ºç©ºææ æ³è§£æï¼è¿å空å表 |
| | | */ |
| | | List<Dict> getConfigArrayMap(String configKey); |
| | | |
| | | /** |
| | | * æ ¹æ®åæ° key è·åæå®ç±»åçé
置对象 |
| | | * |
| | | * @param configKey åæ° key |
| | | * @param clazz ç®æ 对象类å |
| | | * @param <T> ç®æ 对象æ³å |
| | | * @return 对象å®ä¾ï¼å¦æé
ç½®ä¸ºç©ºææ æ³è§£æï¼è¿å null |
| | | */ |
| | | <T> T getConfigObject(String configKey, Class<T> clazz); |
| | | |
| | | /** |
| | | * æ ¹æ®åæ° key è·åæå®ç±»åçé
ç½®å表 |
| | | * |
| | | * @param configKey åæ° key |
| | | * @param clazz ç®æ å
ç´ ç±»å |
| | | * @param <T> å
ç´ ç±»åæ³å |
| | | * @return æå®ç±»åå表ï¼å¦æé
ç½®ä¸ºç©ºææ æ³è§£æï¼è¿å空å表 |
| | | */ |
| | | <T> List<T> getConfigArray(String configKey, Class<T> clazz); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.service; |
| | | |
| | | import org.dromara.common.core.domain.dto.DeptDTO; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * éç¨ é¨é¨æå¡ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public interface DeptService { |
| | | |
| | | /** |
| | | * éè¿é¨é¨IDæ¥è¯¢é¨é¨åç§° |
| | | * |
| | | * @param deptIds é¨é¨ID串éå·åé |
| | | * @return é¨é¨å称串éå·åé |
| | | */ |
| | | String selectDeptNameByIds(String deptIds); |
| | | |
| | | /** |
| | | * æ ¹æ®é¨é¨IDæ¥è¯¢é¨é¨è´è´£äºº |
| | | * |
| | | * @param deptId é¨é¨IDï¼ç¨äºæå®éè¦æ¥è¯¢çé¨é¨ |
| | | * @return è¿å该é¨é¨çè´è´£äººID |
| | | */ |
| | | Long selectDeptLeaderById(Long deptId); |
| | | |
| | | /** |
| | | * æ¥è¯¢é¨é¨ |
| | | * |
| | | * @return é¨é¨å表 |
| | | */ |
| | | List<DeptDTO> selectDeptsByList(); |
| | | |
| | | /** |
| | | * æ ¹æ®é¨é¨ ID å表æ¥è¯¢é¨é¨åç§°æ å°å
³ç³» |
| | | * |
| | | * @param deptIds é¨é¨ ID å表 |
| | | * @return Mapï¼å
¶ä¸ key 为é¨é¨ IDï¼value 为对åºçé¨é¨åç§° |
| | | */ |
| | | Map<Long, String> selectDeptNamesByIds(List<Long> deptIds); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.service; |
| | | |
| | | import org.dromara.common.core.domain.dto.DictDataDTO; |
| | | import org.dromara.common.core.domain.dto.DictTypeDTO; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * éç¨ åå
¸æå¡ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public interface DictService { |
| | | |
| | | /** |
| | | * åé符 |
| | | */ |
| | | String SEPARATOR = ","; |
| | | |
| | | /** |
| | | * æ ¹æ®åå
¸ç±»åååå
¸å¼è·ååå
¸æ ç¾ |
| | | * |
| | | * @param dictType åå
¸ç±»å |
| | | * @param dictValue åå
¸å¼ |
| | | * @return åå
¸æ ç¾ |
| | | */ |
| | | default String getDictLabel(String dictType, String dictValue) { |
| | | return getDictLabel(dictType, dictValue, SEPARATOR); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®åå
¸ç±»åååå
¸æ ç¾è·ååå
¸å¼ |
| | | * |
| | | * @param dictType åå
¸ç±»å |
| | | * @param dictLabel åå
¸æ ç¾ |
| | | * @return åå
¸å¼ |
| | | */ |
| | | default String getDictValue(String dictType, String dictLabel) { |
| | | return getDictValue(dictType, dictLabel, SEPARATOR); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®åå
¸ç±»åååå
¸å¼è·ååå
¸æ ç¾ |
| | | * |
| | | * @param dictType åå
¸ç±»å |
| | | * @param dictValue åå
¸å¼ |
| | | * @param separator åé符 |
| | | * @return åå
¸æ ç¾ |
| | | */ |
| | | String getDictLabel(String dictType, String dictValue, String separator); |
| | | |
| | | /** |
| | | * æ ¹æ®åå
¸ç±»åååå
¸æ ç¾è·ååå
¸å¼ |
| | | * |
| | | * @param dictType åå
¸ç±»å |
| | | * @param dictLabel åå
¸æ ç¾ |
| | | * @param separator åé符 |
| | | * @return åå
¸å¼ |
| | | */ |
| | | String getDictValue(String dictType, String dictLabel, String separator); |
| | | |
| | | /** |
| | | * è·ååå
¸ä¸ææçåå
¸å¼ä¸æ ç¾ |
| | | * |
| | | * @param dictType åå
¸ç±»å |
| | | * @return dictValue为keyï¼dictLabel为å¼ç»æçMap |
| | | */ |
| | | Map<String, String> getAllDictByDictType(String dictType); |
| | | |
| | | /** |
| | | * æ ¹æ®åå
¸ç±»åæ¥è¯¢è¯¦ç»ä¿¡æ¯ |
| | | * |
| | | * @param dictType åå
¸ç±»å |
| | | * @return åå
¸ç±»å详ç»ä¿¡æ¯ |
| | | */ |
| | | DictTypeDTO getDictType(String dictType); |
| | | |
| | | /** |
| | | * æ ¹æ®åå
¸ç±»åæ¥è¯¢åå
¸æ°æ®å表 |
| | | * |
| | | * @param dictType åå
¸ç±»å |
| | | * @return åå
¸æ°æ®å表 |
| | | */ |
| | | List<DictDataDTO> getDictData(String dictType); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.service; |
| | | |
| | | import org.dromara.common.core.domain.dto.OssDTO; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * éç¨ OSSæå¡ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public interface OssService { |
| | | |
| | | /** |
| | | * éè¿ossIdæ¥è¯¢å¯¹åºçurl |
| | | * |
| | | * @param ossIds ossId串éå·åé |
| | | * @return url串éå·åé |
| | | */ |
| | | String selectUrlByIds(String ossIds); |
| | | |
| | | /** |
| | | * éè¿ossIdæ¥è¯¢å表 |
| | | * |
| | | * @param ossIds ossId串éå·åé |
| | | * @return å表 |
| | | */ |
| | | List<OssDTO> selectByIds(String ossIds); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.service; |
| | | |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * ç¨æ·æéå¤ç |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public interface PermissionService { |
| | | |
| | | /** |
| | | * è·åè§è²æ°æ®æé |
| | | * |
| | | * @param userId ç¨æ·id |
| | | * @return è§è²æéä¿¡æ¯ |
| | | */ |
| | | Set<String> getRolePermission(Long userId); |
| | | |
| | | /** |
| | | * è·åèåæ°æ®æé |
| | | * |
| | | * @param userId ç¨æ·id |
| | | * @return èåæéä¿¡æ¯ |
| | | */ |
| | | Set<String> getMenuPermission(Long userId); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.service; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * éç¨ å²ä½æå¡ |
| | | * |
| | | * @author AprilWind |
| | | */ |
| | | public interface PostService { |
| | | |
| | | /** |
| | | * æ ¹æ®å²ä½ ID å表æ¥è¯¢å²ä½åç§°æ å°å
³ç³» |
| | | * |
| | | * @param postIds å²ä½ ID å表 |
| | | * @return Mapï¼å
¶ä¸ key 为å²ä½ IDï¼value 为对åºçå²ä½åç§° |
| | | */ |
| | | Map<Long, String> selectPostNamesByIds(List<Long> postIds); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.service; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * éç¨ è§è²æå¡ |
| | | * |
| | | * @author AprilWind |
| | | */ |
| | | public interface RoleService { |
| | | |
| | | /** |
| | | * æ ¹æ®è§è² ID å表æ¥è¯¢è§è²åç§°æ å°å
³ç³» |
| | | * |
| | | * @param roleIds è§è² ID å表 |
| | | * @return Mapï¼å
¶ä¸ key 为è§è² IDï¼value 为对åºçè§è²åç§° |
| | | */ |
| | | Map<Long, String> selectRoleNamesByIds(List<Long> roleIds); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.service; |
| | | |
| | | import org.dromara.common.core.domain.dto.TaskAssigneeDTO; |
| | | import org.dromara.common.core.domain.model.TaskAssigneeBody; |
| | | |
| | | /** |
| | | * 工使µè®¾è®¡å¨è·å任塿§è¡äºº |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public interface TaskAssigneeService { |
| | | |
| | | /** |
| | | * æ¥è¯¢è§è²å¹¶è¿åä»»å¡ææ´¾çåè¡¨ï¼æ¯æå页 |
| | | * |
| | | * @param taskQuery æ¥è¯¢æ¡ä»¶ |
| | | * @return åç人 |
| | | */ |
| | | TaskAssigneeDTO selectRolesByTaskAssigneeList(TaskAssigneeBody taskQuery); |
| | | |
| | | /** |
| | | * æ¥è¯¢å²ä½å¹¶è¿åä»»å¡ææ´¾çåè¡¨ï¼æ¯æå页 |
| | | * |
| | | * @param taskQuery æ¥è¯¢æ¡ä»¶ |
| | | * @return åç人 |
| | | */ |
| | | TaskAssigneeDTO selectPostsByTaskAssigneeList(TaskAssigneeBody taskQuery); |
| | | |
| | | /** |
| | | * æ¥è¯¢é¨é¨å¹¶è¿åä»»å¡ææ´¾çåè¡¨ï¼æ¯æå页 |
| | | * |
| | | * @param taskQuery æ¥è¯¢æ¡ä»¶ |
| | | * @return åç人 |
| | | */ |
| | | TaskAssigneeDTO selectDeptsByTaskAssigneeList(TaskAssigneeBody taskQuery); |
| | | |
| | | /** |
| | | * æ¥è¯¢ç¨æ·å¹¶è¿åä»»å¡ææ´¾çåè¡¨ï¼æ¯æå页 |
| | | * |
| | | * @param taskQuery æ¥è¯¢æ¡ä»¶ |
| | | * @return åç人 |
| | | */ |
| | | TaskAssigneeDTO selectUsersByTaskAssigneeList(TaskAssigneeBody taskQuery); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.service; |
| | | |
| | | import org.dromara.common.core.domain.dto.UserDTO; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * éç¨ ç¨æ·æå¡ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public interface UserService { |
| | | |
| | | /** |
| | | * éè¿ç¨æ·IDæ¥è¯¢ç¨æ·è´¦æ· |
| | | * |
| | | * @param userId ç¨æ·ID |
| | | * @return ç¨æ·è´¦æ· |
| | | */ |
| | | String selectUserNameById(Long userId); |
| | | |
| | | /** |
| | | * éè¿ç¨æ·IDæ¥è¯¢ç¨æ·è´¦æ· |
| | | * |
| | | * @param userId ç¨æ·ID |
| | | * @return ç¨æ·åç§° |
| | | */ |
| | | String selectNicknameById(Long userId); |
| | | |
| | | /** |
| | | * éè¿ç¨æ·IDæ¥è¯¢ç¨æ·è´¦æ· |
| | | * |
| | | * @param userIds ç¨æ·ID å¤ä¸ªç¨éå·éå¼ |
| | | * @return ç¨æ·åç§° |
| | | */ |
| | | String selectNicknameByIds(String userIds); |
| | | |
| | | /** |
| | | * éè¿ç¨æ·IDæ¥è¯¢ç¨æ·ææºå· |
| | | * |
| | | * @param userId ç¨æ·id |
| | | * @return ç¨æ·ææºå· |
| | | */ |
| | | String selectPhonenumberById(Long userId); |
| | | |
| | | /** |
| | | * éè¿ç¨æ·IDæ¥è¯¢ç¨æ·é®ç®± |
| | | * |
| | | * @param userId ç¨æ·id |
| | | * @return ç¨æ·é®ç®± |
| | | */ |
| | | String selectEmailById(Long userId); |
| | | |
| | | /** |
| | | * éè¿ç¨æ·IDæ¥è¯¢ç¨æ·å表 |
| | | * |
| | | * @param userIds ç¨æ·ids |
| | | * @return ç¨æ·å表 |
| | | */ |
| | | List<UserDTO> selectListByIds(List<Long> userIds); |
| | | |
| | | /** |
| | | * éè¿è§è²IDæ¥è¯¢ç¨æ·ID |
| | | * |
| | | * @param roleIds è§è²ids |
| | | * @return ç¨æ·ids |
| | | */ |
| | | List<Long> selectUserIdsByRoleIds(List<Long> roleIds); |
| | | |
| | | /** |
| | | * éè¿è§è²IDæ¥è¯¢ç¨æ· |
| | | * |
| | | * @param roleIds è§è²ids |
| | | * @return ç¨æ· |
| | | */ |
| | | List<UserDTO> selectUsersByRoleIds(List<Long> roleIds); |
| | | |
| | | /** |
| | | * éè¿é¨é¨IDæ¥è¯¢ç¨æ· |
| | | * |
| | | * @param deptIds é¨é¨ids |
| | | * @return ç¨æ· |
| | | */ |
| | | List<UserDTO> selectUsersByDeptIds(List<Long> deptIds); |
| | | |
| | | /** |
| | | * éè¿å²ä½IDæ¥è¯¢ç¨æ· |
| | | * |
| | | * @param postIds å²ä½ids |
| | | * @return ç¨æ· |
| | | */ |
| | | List<UserDTO> selectUsersByPostIds(List<Long> postIds); |
| | | |
| | | /** |
| | | * æ ¹æ®ç¨æ· ID å表æ¥è¯¢ç¨æ·åç§°æ å°å
³ç³» |
| | | * |
| | | * @param userIds ç¨æ· ID å表 |
| | | * @return Mapï¼å
¶ä¸ key ä¸ºç¨æ· IDï¼value 为对åºçç¨æ·åç§° |
| | | */ |
| | | Map<Long, String> selectUserNamesByIds(List<Long> userIds); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.service; |
| | | |
| | | import org.dromara.common.core.domain.dto.CompleteTaskDTO; |
| | | import org.dromara.common.core.domain.dto.StartProcessDTO; |
| | | import org.dromara.common.core.domain.dto.StartProcessReturnDTO; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * éç¨ å·¥ä½æµæå¡ |
| | | * |
| | | * @author may |
| | | */ |
| | | public interface WorkflowService { |
| | | |
| | | /** |
| | | * è¿è¡ä¸çå®ä¾ å é¤ç¨å®ä¾ï¼å é¤åå²è®°å½ï¼å é¤ä¸å¡ä¸æµç¨å
³èä¿¡æ¯ |
| | | * |
| | | * @param businessIds ä¸å¡id |
| | | * @return ç»æ |
| | | */ |
| | | boolean deleteInstance(List<String> businessIds); |
| | | |
| | | /** |
| | | * è·åå½åæµç¨ç¶æ |
| | | * |
| | | * @param taskId ä»»å¡id |
| | | * @return ç¶æ |
| | | */ |
| | | String getBusinessStatusByTaskId(Long taskId); |
| | | |
| | | /** |
| | | * è·åå½åæµç¨ç¶æ |
| | | * |
| | | * @param businessId ä¸å¡id |
| | | * @return ç¶æ |
| | | */ |
| | | String getBusinessStatus(String businessId); |
| | | |
| | | /** |
| | | * 设置æµç¨åé |
| | | * |
| | | * @param instanceId æµç¨å®ä¾id |
| | | * @param variable æµç¨åé |
| | | */ |
| | | void setVariable(Long instanceId, Map<String, Object> variable); |
| | | |
| | | /** |
| | | * è·åæµç¨åé |
| | | * |
| | | * @param instanceId æµç¨å®ä¾id |
| | | */ |
| | | Map<String, Object> instanceVariable(Long instanceId); |
| | | |
| | | /** |
| | | * æç
§ä¸å¡idæ¥è¯¢æµç¨å®ä¾id |
| | | * |
| | | * @param businessId ä¸å¡id |
| | | * @return ç»æ |
| | | */ |
| | | Long getInstanceIdByBusinessId(String businessId); |
| | | |
| | | /** |
| | | * æ°å¢ç§æ·æµç¨å®ä¹ |
| | | * |
| | | * @param tenantId ç§æ·id |
| | | */ |
| | | void syncDef(String tenantId); |
| | | |
| | | /** |
| | | * å¯å¨æµç¨ |
| | | * |
| | | * @param startProcess åæ° |
| | | * @return ç»æ |
| | | */ |
| | | StartProcessReturnDTO startWorkFlow(StartProcessDTO startProcess); |
| | | |
| | | /** |
| | | * åçä»»å¡ |
| | | * ç³»ç»åå°åèµ·å®¡æ¹ æ ç¨æ·ä¿¡æ¯ éè¦å¿½ç¥æé |
| | | * completeTask.getVariables().put("ignore", true); |
| | | * |
| | | * @param completeTask åæ° |
| | | * @return ç»æ |
| | | */ |
| | | boolean completeTask(CompleteTaskDTO completeTask); |
| | | |
| | | /** |
| | | * åçä»»å¡ |
| | | * |
| | | * @param taskId ä»»å¡ID |
| | | * @param message åçæè§ |
| | | * @return ç»æ |
| | | */ |
| | | boolean completeTask(Long taskId, String message); |
| | | |
| | | /** |
| | | * å¯å¨æµç¨å¹¶åç第ä¸ä¸ªä»»å¡ |
| | | * |
| | | * @param startProcess åæ° |
| | | * @return ç»æ |
| | | */ |
| | | boolean startCompleteTask(StartProcessDTO startProcess); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils; |
| | | |
| | | import cn.hutool.core.date.DateUnit; |
| | | import cn.hutool.core.date.DateUtil; |
| | | import org.apache.commons.lang3.time.DateFormatUtils; |
| | | import org.dromara.common.core.enums.FormatsType; |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | |
| | | import java.lang.management.ManagementFactory; |
| | | import java.text.ParseException; |
| | | import java.text.SimpleDateFormat; |
| | | import java.time.*; |
| | | import java.util.Date; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * æ¶é´å·¥å
·ç±» |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | public class DateUtils extends org.apache.commons.lang3.time.DateUtils { |
| | | private static final String[] PARSE_PATTERNS = { |
| | | "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", |
| | | "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", |
| | | "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; |
| | | |
| | | @Deprecated |
| | | private DateUtils() { |
| | | } |
| | | |
| | | /** |
| | | * è·åå½åæ¥æåæ¶é´ |
| | | * |
| | | * @return å½åæ¥æåæ¶é´ç Date 对象表示 |
| | | */ |
| | | public static Date getNowDate() { |
| | | return new Date(); |
| | | } |
| | | |
| | | /** |
| | | * è·åå½åæ¥æçåç¬¦ä¸²è¡¨ç¤ºï¼æ ¼å¼ä¸ºYYYY-MM-DD |
| | | * |
| | | * @return å½åæ¥æçå符串表示 |
| | | */ |
| | | public static String getDate() { |
| | | return dateTimeNow(FormatsType.YYYY_MM_DD); |
| | | } |
| | | |
| | | /** |
| | | * è·åå½åæ¥æçåç¬¦ä¸²è¡¨ç¤ºï¼æ ¼å¼ä¸ºyyyyMMdd |
| | | * |
| | | * @return å½åæ¥æçå符串表示 |
| | | */ |
| | | public static String getCurrentDate() { |
| | | return DateFormatUtils.format(new Date(), FormatsType.YYYYMMDD.getTimeFormat()); |
| | | } |
| | | |
| | | /** |
| | | * è·åå½åæ¥æçè·¯å¾æ ¼å¼åç¬¦ä¸²ï¼æ ¼å¼ä¸º"yyyy/MM/dd" |
| | | * |
| | | * @return å½åæ¥æçè·¯å¾æ ¼å¼å符串 |
| | | */ |
| | | public static String datePath() { |
| | | Date now = new Date(); |
| | | return DateFormatUtils.format(now, FormatsType.YYYY_MM_DD_SLASH.getTimeFormat()); |
| | | } |
| | | |
| | | /** |
| | | * è·åå½åæ¶é´çåç¬¦ä¸²è¡¨ç¤ºï¼æ ¼å¼ä¸ºYYYY-MM-DD HH:MM:SS |
| | | * |
| | | * @return å½åæ¶é´çå符串表示 |
| | | */ |
| | | public static String getTime() { |
| | | return dateTimeNow(FormatsType.YYYY_MM_DD_HH_MM_SS); |
| | | } |
| | | |
| | | /** |
| | | * è·åå½åæ¶é´çåç¬¦ä¸²è¡¨ç¤ºï¼æ ¼å¼ä¸º "HH:MM:SS" |
| | | * |
| | | * @return å½åæ¶é´çåç¬¦ä¸²è¡¨ç¤ºï¼æ ¼å¼ä¸º "HH:MM:SS" |
| | | */ |
| | | public static String getTimeWithHourMinuteSecond() { |
| | | return dateTimeNow(FormatsType.HH_MM_SS); |
| | | } |
| | | |
| | | /** |
| | | * è·åå½åæ¥æåæ¶é´çåç¬¦ä¸²è¡¨ç¤ºï¼æ ¼å¼ä¸ºYYYYMMDDHHMMSS |
| | | * |
| | | * @return å½åæ¥æåæ¶é´çå符串表示 |
| | | */ |
| | | public static String dateTimeNow() { |
| | | return dateTimeNow(FormatsType.YYYYMMDDHHMMSS); |
| | | } |
| | | |
| | | /** |
| | | * è·åå½åæ¥æåæ¶é´çæå®æ ¼å¼çå符串表示 |
| | | * |
| | | * @param format æ¥ææ¶é´æ ¼å¼ï¼ä¾å¦"YYYY-MM-DD HH:MM:SS" |
| | | * @return å½åæ¥æåæ¶é´çå符串表示 |
| | | */ |
| | | public static String dateTimeNow(final FormatsType format) { |
| | | return parseDateToStr(format, new Date()); |
| | | } |
| | | |
| | | /** |
| | | * 尿宿¥ææ ¼å¼å为 YYYY-MM-DD æ ¼å¼çå符串 |
| | | * |
| | | * @param date è¦æ ¼å¼åçæ¥æå¯¹è±¡ |
| | | * @return æ ¼å¼ååçæ¥æå符串 |
| | | */ |
| | | public static String formatDate(final Date date) { |
| | | return parseDateToStr(FormatsType.YYYY_MM_DD, date); |
| | | } |
| | | |
| | | /** |
| | | * 尿宿¥ææ ¼å¼å为 YYYY-MM-DD HH:MM:SS æ ¼å¼çå符串 |
| | | * |
| | | * @param date è¦æ ¼å¼åçæ¥æå¯¹è±¡ |
| | | * @return æ ¼å¼ååçæ¥ææ¶é´å符串 |
| | | */ |
| | | public static String formatDateTime(final Date date) { |
| | | return parseDateToStr(FormatsType.YYYY_MM_DD_HH_MM_SS, date); |
| | | } |
| | | |
| | | /** |
| | | * 尿宿¥ææç
§æå®æ ¼å¼è¿è¡æ ¼å¼å |
| | | * |
| | | * @param format è¦ä½¿ç¨çæ¥ææ¶é´æ ¼å¼ï¼ä¾å¦"YYYY-MM-DD HH:MM:SS" |
| | | * @param date è¦æ ¼å¼åçæ¥æå¯¹è±¡ |
| | | * @return æ ¼å¼ååçæ¥ææ¶é´å符串 |
| | | */ |
| | | public static String parseDateToStr(final FormatsType format, final Date date) { |
| | | return new SimpleDateFormat(format.getTimeFormat()).format(date); |
| | | } |
| | | |
| | | /** |
| | | * 尿宿 ¼å¼çæ¥ææ¶é´å符串转æ¢ä¸º Date 对象 |
| | | * |
| | | * @param format è¦è§£æçæ¥ææ¶é´æ ¼å¼ï¼ä¾å¦"YYYY-MM-DD HH:MM:SS" |
| | | * @param ts è¦è§£æçæ¥ææ¶é´å符串 |
| | | * @return è§£æåç Date 对象 |
| | | * @throws RuntimeException å¦æè§£æè¿ç¨ä¸åçå¼å¸¸ |
| | | */ |
| | | public static Date parseDateTime(final FormatsType format, final String ts) { |
| | | try { |
| | | return new SimpleDateFormat(format.getTimeFormat()).parse(ts); |
| | | } catch (ParseException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°å¯¹è±¡è½¬æ¢ä¸ºæ¥æå¯¹è±¡ |
| | | * |
| | | * @param str è¦è½¬æ¢ç对象ï¼é常æ¯å符串 |
| | | * @return 转æ¢åçæ¥æå¯¹è±¡ï¼å¦æè½¬æ¢å¤±è´¥æè¾å
¥ä¸ºnullï¼åè¿ånull |
| | | */ |
| | | public static Date parseDate(Object str) { |
| | | if (str == null) { |
| | | return null; |
| | | } |
| | | try { |
| | | return parseDate(str.toString(), PARSE_PATTERNS); |
| | | } catch (ParseException e) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è·åæå¡å¨å¯å¨æ¶é´ |
| | | * |
| | | * @return æå¡å¨å¯å¨æ¶é´ç Date 对象表示 |
| | | */ |
| | | public static Date getServerStartDate() { |
| | | long time = ManagementFactory.getRuntimeMXBean().getStartTime(); |
| | | return new Date(time); |
| | | } |
| | | |
| | | /** |
| | | * 计ç®ä¸¤ä¸ªæ¶é´ä¹é´çæ¶é´å·®ï¼å¹¶ä»¥æå®åä½è¿åï¼ç»å¯¹å¼ï¼ |
| | | * |
| | | * @param start èµ·å§æ¶é´ |
| | | * @param end ç»ææ¶é´ |
| | | * @param unit æéè¿åçæ¶é´åä½ï¼DAYSãHOURSãMINUTESãSECONDSãMILLISECONDSãMICROSECONDSãNANOSECONDSï¼ |
| | | * @return æ¶é´å·®çç»å¯¹å¼ï¼ä»¥æå®åä½è¡¨ç¤º |
| | | */ |
| | | public static long difference(Date start, Date end, TimeUnit unit) { |
| | | // è®¡ç®æ¶é´å·®ï¼åä½ä¸ºæ¯«ç§ï¼åç»å¯¹å¼é¿å
è´æ° |
| | | long diffInMillis = Math.abs(end.getTime() - start.getTime()); |
| | | |
| | | // æ ¹æ®ç®æ åä½è½¬æ¢æ¶é´å·® |
| | | return switch (unit) { |
| | | case DAYS -> diffInMillis / TimeUnit.DAYS.toMillis(1); |
| | | case HOURS -> diffInMillis / TimeUnit.HOURS.toMillis(1); |
| | | case MINUTES -> diffInMillis / TimeUnit.MINUTES.toMillis(1); |
| | | case SECONDS -> diffInMillis / TimeUnit.SECONDS.toMillis(1); |
| | | case MILLISECONDS -> diffInMillis; |
| | | case MICROSECONDS -> TimeUnit.MILLISECONDS.toMicros(diffInMillis); |
| | | case NANOSECONDS -> TimeUnit.MILLISECONDS.toNanos(diffInMillis); |
| | | }; |
| | | } |
| | | |
| | | /** |
| | | * 计ç®ä¸¤ä¸ªæ¥æä¹é´çæ¶é´å·®ï¼å¹¶ä»¥å¤©ãå°æ¶ååéçæ ¼å¼è¿å |
| | | * |
| | | * @param endDate ç»ææ¥æ |
| | | * @param nowDate å½åæ¥æ |
| | | * @return 表示æ¶é´å·®çåç¬¦ä¸²ï¼æ ¼å¼ä¸º"天 å°æ¶ åé" |
| | | */ |
| | | public static String getDatePoor(Date endDate, Date nowDate) { |
| | | long diffInMillis = endDate.getTime() - nowDate.getTime(); |
| | | long day = TimeUnit.MILLISECONDS.toDays(diffInMillis); |
| | | long hour = TimeUnit.MILLISECONDS.toHours(diffInMillis) % 24; |
| | | long min = TimeUnit.MILLISECONDS.toMinutes(diffInMillis) % 60; |
| | | return String.format("%d天 %då°æ¶ %dåé", day, hour, min); |
| | | } |
| | | |
| | | /** |
| | | * 计ç®ä¸¤ä¸ªæ¶é´ç¹çå·®å¼ï¼å¤©ãå°æ¶ãåéãç§ï¼ï¼å½å¼ä¸º0æ¶ä¸æ¾ç¤ºè¯¥åä½ |
| | | * |
| | | * @param endDate ç»ææ¶é´ |
| | | * @param nowDate å½åæ¶é´ |
| | | * @return æ¶é´å·®åç¬¦ä¸²ï¼æ ¼å¼ä¸º "x天 xå°æ¶ xåé xç§"ï¼è¥ä¸º 0 å䏿¾ç¤º |
| | | */ |
| | | public static String getTimeDifference(Date endDate, Date nowDate) { |
| | | long diffInMillis = endDate.getTime() - nowDate.getTime(); |
| | | long day = TimeUnit.MILLISECONDS.toDays(diffInMillis); |
| | | long hour = TimeUnit.MILLISECONDS.toHours(diffInMillis) % 24; |
| | | long min = TimeUnit.MILLISECONDS.toMinutes(diffInMillis) % 60; |
| | | long sec = TimeUnit.MILLISECONDS.toSeconds(diffInMillis) % 60; |
| | | // æå»ºæ¶é´å·®åç¬¦ä¸²ï¼æ¡ä»¶æ¯å¼ä¸ä¸º0ææ¾ç¤º |
| | | StringBuilder result = new StringBuilder(); |
| | | if (day > 0) { |
| | | result.append(String.format("%d天 ", day)); |
| | | } |
| | | if (hour > 0) { |
| | | result.append(String.format("%då°æ¶ ", hour)); |
| | | } |
| | | if (min > 0) { |
| | | result.append(String.format("%dåé ", min)); |
| | | } |
| | | if (sec > 0) { |
| | | result.append(String.format("%dç§", sec)); |
| | | } |
| | | return result.length() > 0 ? result.toString().trim() : "0ç§"; |
| | | } |
| | | |
| | | /** |
| | | * å° LocalDateTime 对象转æ¢ä¸º Date 对象 |
| | | * |
| | | * @param temporalAccessor è¦è½¬æ¢ç LocalDateTime 对象 |
| | | * @return 转æ¢åç Date 对象 |
| | | */ |
| | | public static Date toDate(LocalDateTime temporalAccessor) { |
| | | ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault()); |
| | | return Date.from(zdt.toInstant()); |
| | | } |
| | | |
| | | /** |
| | | * å° LocalDate 对象转æ¢ä¸º Date 对象 |
| | | * |
| | | * @param temporalAccessor è¦è½¬æ¢ç LocalDate 对象 |
| | | * @return 转æ¢åç Date 对象 |
| | | */ |
| | | public static Date toDate(LocalDate temporalAccessor) { |
| | | LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0)); |
| | | ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault()); |
| | | return Date.from(zdt.toInstant()); |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªæ¥æèå´ |
| | | * |
| | | * @param startDate å¼å§æ¥æ |
| | | * @param endDate ç»ææ¥æ |
| | | * @param maxValue æå¤§æ¶é´è·¨åº¦çéå¶å¼ |
| | | * @param unit æ¶é´è·¨åº¦çåä½ï¼å¯éæ© "DAYS"ã"HOURS" æ "MINUTES" |
| | | */ |
| | | public static void validateDateRange(Date startDate, Date endDate, int maxValue, TimeUnit unit) { |
| | | // æ ¡éªç»ææ¥æä¸è½æ©äºå¼å§æ¥æ |
| | | if (endDate.before(startDate)) { |
| | | throw new ServiceException("ç»ææ¥æä¸è½æ©äºå¼å§æ¥æ"); |
| | | } |
| | | |
| | | // è®¡ç®æ¶é´è·¨åº¦ |
| | | long diffInMillis = endDate.getTime() - startDate.getTime(); |
| | | |
| | | // æ ¹æ®åä½è½¬æ¢æ¶é´è·¨åº¦ |
| | | long diff = switch (unit) { |
| | | case DAYS -> TimeUnit.MILLISECONDS.toDays(diffInMillis); |
| | | case HOURS -> TimeUnit.MILLISECONDS.toHours(diffInMillis); |
| | | case MINUTES -> TimeUnit.MILLISECONDS.toMinutes(diffInMillis); |
| | | default -> throw new IllegalArgumentException("䏿¯æçæ¶é´åä½"); |
| | | }; |
| | | |
| | | // æ ¡éªæ¶é´è·¨åº¦ä¸è¶
è¿æå¤§éå¶ |
| | | if (diff > maxValue) { |
| | | throw new ServiceException("æå¤§æ¶é´è·¨åº¦ä¸º {} {}", maxValue, unit.toString().toLowerCase()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®æå®æ¥ææ¶é´è·åæ¶é´æ®µï¼åæ¨ / ä¸å / ä¸å / ä¸å / æä¸ï¼ |
| | | * |
| | | * @param date æ¥ææ¶é´ |
| | | * @return æ¶é´æ®µæè¿° |
| | | */ |
| | | public static String getTodayHour(Date date) { |
| | | int hour = DateUtil.hour(date, true); |
| | | if (hour <= 6) { |
| | | return "忍"; |
| | | } else if (hour < 12) { |
| | | return "ä¸å"; |
| | | } else if (hour == 12) { |
| | | return "ä¸å"; |
| | | } else if (hour <= 18) { |
| | | return "ä¸å"; |
| | | } else { |
| | | return "æä¸"; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°æ¥ææ ¼å¼å为仿微信çå好æ¶é´ |
| | | * <p> |
| | | * è§å说æï¼ |
| | | * 1. æªæ¥æ¶é´ï¼yyyy-MM-dd HH:mm |
| | | * 2. ä»å¤©ï¼ |
| | | * - 1 åéå
ï¼åå |
| | | * - 1 å°æ¶å
ï¼X åéå |
| | | * - è¶
è¿ 1 å°æ¶ï¼åæ¨/ä¸å/ä¸å/ä¸å/æä¸ HH:mm |
| | | * 3. æ¨å¤©ï¼æ¨å¤© HH:mm |
| | | * 4. æ¬å¨ï¼å¨X HH:mm |
| | | * 5. ä»å¹´å
ï¼MM-dd HH:mm |
| | | * 6. éä»å¹´ï¼yyyy-MM-dd HH:mm |
| | | * |
| | | * @param date æ¥ææ¶é´ |
| | | * @return æ ¼å¼ååçæ¶é´æè¿° |
| | | */ |
| | | public static String formatFriendlyTime(Date date) { |
| | | if (date == null) { |
| | | return ""; |
| | | } |
| | | Date now = DateUtil.date(); |
| | | |
| | | // æªæ¥æ¶é´æéä»å¹´ |
| | | if (date.after(now) || DateUtil.year(date) != DateUtil.year(now)) { |
| | | return parseDateToStr(FormatsType.YYYY_MM_DD_HH_MM, date); |
| | | } |
| | | |
| | | // ä»å¤© |
| | | if (DateUtil.isSameDay(date, now)) { |
| | | long minutes = DateUtil.between(date, now, DateUnit.MINUTE); |
| | | if (minutes < 1) { |
| | | return "åå"; |
| | | } |
| | | if (minutes < 60) { |
| | | return minutes + "åéå"; |
| | | } |
| | | return getTodayHour(date) + " " + DateUtil.format(date, "HH:mm"); |
| | | } |
| | | |
| | | // æ¨å¤© |
| | | if (DateUtil.isSameDay(date, DateUtil.yesterday())) { |
| | | return "æ¨å¤© " + DateUtil.format(date, "HH:mm"); |
| | | } |
| | | |
| | | // æ¬å¨ |
| | | if (DateUtil.isSameWeek(date, now, true)) { |
| | | return DateUtil.dayOfWeekEnum(date).toChinese("å¨") |
| | | + " " + DateUtil.format(date, "HH:mm"); |
| | | } |
| | | |
| | | // ä»å¹´å
å
¶å®æ¶é´ |
| | | return DateUtil.format(date, "MM-dd HH:mm"); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils; |
| | | |
| | | import cn.hutool.core.util.DesensitizedUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | /** |
| | | * è±æå·¥å
·ç±» |
| | | * |
| | | * @author AprilWind |
| | | */ |
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE) |
| | | public class DesensitizedUtils extends DesensitizedUtil { |
| | | |
| | | /** |
| | | * çµæ´»è±ææ¹æ³ |
| | | * |
| | | * @param value åå§å符串 |
| | | * @param prefixVisible åé¢å¯è§é¿åº¦ |
| | | * @param suffixVisible åé¢å¯è§é¿åº¦ |
| | | * @param maskLength ä¸é´æ©ç é¿åº¦ï¼åºå®æ¾ç¤ºå¤å° *ï¼å¦ææ»é¿åº¦ä¸è¶³åèªå¨ç¼©åï¼ |
| | | * @return è±æåå符串 |
| | | */ |
| | | public static String mask(String value, int prefixVisible, int suffixVisible, int maskLength) { |
| | | if (StrUtil.isBlank(value)) { |
| | | return value; |
| | | } |
| | | |
| | | int len = value.length(); |
| | | int prefixMaskLimit = prefixVisible + maskLength; |
| | | int fullLimit = prefixMaskLimit + suffixVisible; |
| | | |
| | | // è§å 1ï¼é¿åº¦ <= ä¸é´æ©ç é¿åº¦ â å
¨æ©ç |
| | | if (len <= maskLength) { |
| | | return StrUtil.repeat('*', len); |
| | | } |
| | | String mask = StrUtil.repeat('*', maskLength); |
| | | |
| | | // è§å 2ï¼é¿åº¦ <= åç¼ + ä¸é´æ©ç |
| | | if (len <= prefixMaskLimit) { |
| | | return value.substring(0, len - maskLength) + mask; |
| | | } |
| | | |
| | | String prefix = value.substring(0, prefixVisible); |
| | | |
| | | // è§å 3ï¼é¿åº¦ <= åç¼ + ä¸é´æ©ç + åç¼ |
| | | if (len <= fullLimit) { |
| | | int suffixLen = len - prefixMaskLimit; |
| | | return prefix + mask + value.substring(len - suffixLen); |
| | | } |
| | | |
| | | // è§å 4ï¼æ åå½¢æ |
| | | return prefix + mask + value.substring(len - suffixVisible); |
| | | } |
| | | |
| | | /** |
| | | * é«å®å
¨çº§å«è±ææ¹æ³ï¼Token / ç§é¥ï¼ |
| | | * |
| | | * @param value åå§å符串 |
| | | * @param prefixVisible åé¢å¯è§é¿åº¦ï¼æ¨è0~4ï¼ |
| | | * @param suffixVisible åé¢å¯è§é¿åº¦ï¼æ¨è0~4ï¼ |
| | | * @return è±æåå符串 |
| | | */ |
| | | public static String maskHighSecurity(String value, int prefixVisible, int suffixVisible) { |
| | | if (StrUtil.isBlank(value)) { |
| | | return value; |
| | | } |
| | | int len = value.length(); |
| | | |
| | | // è§å1ï¼é¿åº¦ <= åç¼å¯è§é¿åº¦ â å
¨é¨æ©ç |
| | | if (len <= prefixVisible) { |
| | | return StrUtil.repeat('*', len); |
| | | } |
| | | |
| | | // è§å2ï¼é¿åº¦ <= åç¼ + åç¼å¯è§é¿åº¦ â ä¼å
æ©ç åé¢ |
| | | if (len <= prefixVisible + suffixVisible) { |
| | | return value.substring(0, len - prefixVisible) + StrUtil.repeat('*', prefixVisible); |
| | | } |
| | | |
| | | // è§å3ï¼æ åå½¢æ â ååå¯è§ï¼ä¸é´å
¨é¨æ©ç |
| | | return value.substring(0, prefixVisible) |
| | | + StrUtil.repeat('*', len - prefixVisible - suffixVisible) |
| | | + value.substring(len - suffixVisible); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.map.MapUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import io.github.linpeilie.Converter; |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * Mapstruct å·¥å
·ç±» |
| | | * <p>åèææ¡£ï¼<a href="https://mapstruct.plus/introduction/quick-start.html">mapstruct-plus</a></p> |
| | | * |
| | | * |
| | | * @author Michelle.Chung |
| | | */ |
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE) |
| | | public class MapstructUtils { |
| | | |
| | | private final static Converter CONVERTER = SpringUtils.getBean(Converter.class); |
| | | |
| | | /** |
| | | * å° T ç±»å对象ï¼è½¬æ¢ä¸º desc ç±»åç对象并è¿å |
| | | * |
| | | * @param source æ°æ®æ¥æºå®ä½ |
| | | * @param desc æè¿°å¯¹è±¡ 转æ¢åç对象 |
| | | * @return desc |
| | | */ |
| | | public static <T, V> V convert(T source, Class<V> desc) { |
| | | if (ObjectUtil.isNull(source)) { |
| | | return null; |
| | | } |
| | | if (ObjectUtil.isNull(desc)) { |
| | | return null; |
| | | } |
| | | return CONVERTER.convert(source, desc); |
| | | } |
| | | |
| | | /** |
| | | * å° T ç±»åå¯¹è±¡ï¼æç
§é
ç½®çæ å°å段è§åï¼ç» desc ç±»åç对象èµå¼å¹¶è¿å desc 对象 |
| | | * |
| | | * @param source æ°æ®æ¥æºå®ä½ |
| | | * @param desc 转æ¢åç对象 |
| | | * @return desc |
| | | */ |
| | | public static <T, V> V convert(T source, V desc) { |
| | | if (ObjectUtil.isNull(source)) { |
| | | return null; |
| | | } |
| | | if (ObjectUtil.isNull(desc)) { |
| | | return null; |
| | | } |
| | | return CONVERTER.convert(source, desc); |
| | | } |
| | | |
| | | /** |
| | | * å° T ç±»åçéåï¼è½¬æ¢ä¸º desc ç±»åçéåå¹¶è¿å |
| | | * |
| | | * @param sourceList æ°æ®æ¥æºå®ä½å表 |
| | | * @param desc æè¿°å¯¹è±¡ 转æ¢åç对象 |
| | | * @return desc |
| | | */ |
| | | public static <T, V> List<V> convert(List<T> sourceList, Class<V> desc) { |
| | | if (ObjectUtil.isNull(sourceList)) { |
| | | return null; |
| | | } |
| | | if (CollUtil.isEmpty(sourceList)) { |
| | | return CollUtil.newArrayList(); |
| | | } |
| | | return CONVERTER.convert(sourceList, desc); |
| | | } |
| | | |
| | | /** |
| | | * å° Map 转æ¢ä¸º beanClass ç±»åçéåå¹¶è¿å |
| | | * |
| | | * @param map æ°æ®æ¥æº |
| | | * @param beanClass beanç±» |
| | | * @return bean对象 |
| | | */ |
| | | public static <T> T convert(Map<String, Object> map, Class<T> beanClass) { |
| | | if (MapUtil.isEmpty(map)) { |
| | | return null; |
| | | } |
| | | if (ObjectUtil.isNull(beanClass)) { |
| | | return null; |
| | | } |
| | | return CONVERTER.convert(map, beanClass); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils; |
| | | |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | import org.springframework.context.MessageSource; |
| | | import org.springframework.context.NoSuchMessageException; |
| | | import org.springframework.context.i18n.LocaleContextHolder; |
| | | |
| | | /** |
| | | * è·åi18nèµæºæä»¶ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE) |
| | | public class MessageUtils { |
| | | |
| | | private static final MessageSource MESSAGE_SOURCE = SpringUtils.getBean(MessageSource.class); |
| | | |
| | | /** |
| | | * æ ¹æ®æ¶æ¯é®ååæ° è·åæ¶æ¯ å§æç»spring messageSource |
| | | * |
| | | * @param code æ¶æ¯é® |
| | | * @param args åæ° |
| | | * @return è·åå½é
åç¿»è¯å¼ |
| | | */ |
| | | public static String message(String code, Object... args) { |
| | | try { |
| | | return MESSAGE_SOURCE.getMessage(code, args, LocaleContextHolder.getLocale()); |
| | | } catch (NoSuchMessageException e) { |
| | | return code; |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils; |
| | | |
| | | import cn.hutool.core.lang.PatternPool; |
| | | import cn.hutool.core.net.NetUtil; |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.core.utils.regex.RegexUtils; |
| | | |
| | | import java.net.Inet6Address; |
| | | import java.net.InetAddress; |
| | | import java.net.UnknownHostException; |
| | | |
| | | /** |
| | | * å¢å¼ºç½ç»ç¸å
³å·¥å
·ç±» |
| | | * |
| | | * @author ç§è¾æªå¯ |
| | | */ |
| | | @Slf4j |
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE) |
| | | public class NetUtils extends NetUtil { |
| | | |
| | | /** |
| | | * 夿æ¯å¦ä¸ºIPv6å°å |
| | | * |
| | | * @param ip IPå°å |
| | | * @return æ¯å¦ä¸ºIPv6å°å |
| | | */ |
| | | public static boolean isIPv6(String ip) { |
| | | try { |
| | | // 夿æ¯å¦ä¸ºIPv6å°å |
| | | return InetAddress.getByName(ip) instanceof Inet6Address; |
| | | } catch (UnknownHostException e) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 夿IPv6å°åæ¯å¦ä¸ºå
ç½å°å |
| | | * <br><br> |
| | | * 以ä¸å°åå°å½ç±»ä¸ºæ¬å°å°åï¼å¦æä¸å¡åºæ¯æéè¦ï¼è¯·æ ¹æ®éæ±èªè¡å¤çï¼ |
| | | * <pre> |
| | | * éé
符å°å 0:0:0:0:0:0:0:0 |
| | | * é¾è·¯æ¬å°å°å fe80::/10 |
| | | * å¯ä¸æ¬å°å°å fec0::/10 |
| | | * ç¯åå°å ::1 |
| | | * </pre> |
| | | * |
| | | * @param ip IPå°å |
| | | * @return æ¯å¦ä¸ºå
ç½å°å |
| | | */ |
| | | public static boolean isInnerIPv6(String ip) { |
| | | try { |
| | | // 夿æ¯å¦ä¸ºIPv6å°å |
| | | if (InetAddress.getByName(ip) instanceof Inet6Address inet6Address) { |
| | | // isAnyLocalAddress 夿æ¯å¦ä¸ºéé
符å°åï¼é常ä¸ä¼å°å
¶è§ä¸ºå
ç½å°åï¼æ ¹æ®ä¸å¡åºæ¯èªè¡å¤ç夿 |
| | | // isLinkLocalAddress 夿æ¯å¦ä¸ºé¾è·¯æ¬å°å°åï¼é常ä¸ç®å
ç½å°åï¼æ¯å¦ååå½å±äºå
ç½éè¦æ ¹æ®ä¸å¡åºæ¯èªè¡å¤ç夿 |
| | | // isLoopbackAddress 夿æ¯å¦ä¸ºç¯åå°åï¼ä¸IPv4ç 127.0.0.1 åçï¼ç¨äºè¡¨ç¤ºæ¬æº |
| | | // isSiteLocalAddress 夿æ¯å¦ä¸ºæ¬å°ç«ç¹å°åï¼IPv6å¯ä¸æ¬å°å°åï¼Unique Local Addressesï¼ç®ç§°ULAï¼ |
| | | if (inet6Address.isAnyLocalAddress() |
| | | || inet6Address.isLinkLocalAddress() |
| | | || inet6Address.isLoopbackAddress() |
| | | || inet6Address.isSiteLocalAddress()) { |
| | | return true; |
| | | } |
| | | } |
| | | } catch (UnknownHostException e) { |
| | | // 注æï¼isInnerIPv6æ¹æ³åisIPv6æ¹æ³çéç¨èå´ä¸åï¼æä»¥æ¤å¤ä¸è½å¿½ç¥å
¶å¼å¸¸ä¿¡æ¯ã |
| | | throw new IllegalArgumentException("Invalid IPv6 address!", e); |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦ä¸ºIPv4å°å |
| | | * |
| | | * @param ip IPå°å |
| | | * @return æ¯å¦ä¸ºIPv4å°å |
| | | */ |
| | | public static boolean isIPv4(String ip) { |
| | | return RegexUtils.isMatch(PatternPool.IPV4, ip); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils;
|
| | |
|
| | | import cn.hutool.core.util.ObjectUtil;
|
| | | import lombok.AccessLevel;
|
| | | import lombok.NoArgsConstructor;
|
| | |
|
| | | import java.util.function.Function;
|
| | |
|
| | | /**
|
| | | * 对象工å
·ç±»
|
| | | *
|
| | | * @author ç§è¾æªå¯
|
| | | */
|
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE)
|
| | | public class ObjectUtils extends ObjectUtil {
|
| | |
|
| | | /**
|
| | | * å¦æå¯¹è±¡ä¸ä¸ºç©ºï¼åè·å对象ä¸çæä¸ªå段 ObjectUtils.notNullGetter(user, User::getName);
|
| | | *
|
| | | * @param obj 对象
|
| | | * @param func è·åæ¹æ³
|
| | | * @return å¯¹è±¡åæ®µ
|
| | | */
|
| | | public static <T, E> E notNullGetter(T obj, Function<T, E> func) {
|
| | | if (isNotNull(obj) && isNotNull(func)) {
|
| | | return func.apply(obj);
|
| | | }
|
| | | return null;
|
| | | }
|
| | |
|
| | | /**
|
| | | * å¦æå¯¹è±¡ä¸ä¸ºç©ºï¼åè·å对象ä¸çæä¸ªå段ï¼å¦åè¿åé»è®¤å¼
|
| | | *
|
| | | * @param obj 对象
|
| | | * @param func è·åæ¹æ³
|
| | | * @param defaultValue é»è®¤å¼
|
| | | * @return å¯¹è±¡åæ®µ
|
| | | */
|
| | | public static <T, E> E notNullGetter(T obj, Function<T, E> func, E defaultValue) {
|
| | | if (isNotNull(obj) && isNotNull(func)) {
|
| | | return func.apply(obj);
|
| | | }
|
| | | return defaultValue;
|
| | | }
|
| | |
|
| | | /**
|
| | | * 妿å¼ä¸ä¸ºç©ºï¼åè¿åå¼ï¼å¦åè¿åé»è®¤å¼
|
| | | *
|
| | | * @param obj 对象
|
| | | * @param defaultValue é»è®¤å¼
|
| | | * @return å¯¹è±¡åæ®µ
|
| | | */
|
| | | public static <T> T notNull(T obj, T defaultValue) {
|
| | | if (isNotNull(obj)) {
|
| | | return obj;
|
| | | }
|
| | | return defaultValue;
|
| | | }
|
| | |
|
| | | }
|
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils; |
| | | |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.extra.servlet.JakartaServletUtil; |
| | | import cn.hutool.http.HttpStatus; |
| | | import jakarta.servlet.ServletRequest; |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import jakarta.servlet.http.HttpSession; |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | import org.springframework.http.MediaType; |
| | | import org.springframework.util.LinkedCaseInsensitiveMap; |
| | | import org.springframework.web.context.request.RequestAttributes; |
| | | import org.springframework.web.context.request.RequestContextHolder; |
| | | import org.springframework.web.context.request.ServletRequestAttributes; |
| | | |
| | | import java.io.IOException; |
| | | import java.net.URLDecoder; |
| | | import java.net.URLEncoder; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.util.Collections; |
| | | import java.util.Enumeration; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 客æ·ç«¯å·¥å
·ç±»ï¼æä¾è·å请æ±åæ°ãååºå¤çã头é¨ä¿¡æ¯çå¸¸ç¨æä½ |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE) |
| | | public class ServletUtils extends JakartaServletUtil { |
| | | |
| | | /** |
| | | * è·åæå®åç§°ç String ç±»åç请æ±åæ° |
| | | * |
| | | * @param name åæ°å |
| | | * @return åæ°å¼ |
| | | */ |
| | | public static String getParameter(String name) { |
| | | return getRequest().getParameter(name); |
| | | } |
| | | |
| | | /** |
| | | * è·åæå®åç§°ç String ç±»åç请æ±åæ°ï¼è¥åæ°ä¸åå¨ï¼åè¿åé»è®¤å¼ |
| | | * |
| | | * @param name åæ°å |
| | | * @param defaultValue é»è®¤å¼ |
| | | * @return 忰弿é»è®¤å¼ |
| | | */ |
| | | public static String getParameter(String name, String defaultValue) { |
| | | return Convert.toStr(getRequest().getParameter(name), defaultValue); |
| | | } |
| | | |
| | | /** |
| | | * è·åæå®åç§°ç Integer ç±»åç请æ±åæ° |
| | | * |
| | | * @param name åæ°å |
| | | * @return åæ°å¼ |
| | | */ |
| | | public static Integer getParameterToInt(String name) { |
| | | return Convert.toInt(getRequest().getParameter(name)); |
| | | } |
| | | |
| | | /** |
| | | * è·åæå®åç§°ç Integer ç±»åç请æ±åæ°ï¼è¥åæ°ä¸åå¨ï¼åè¿åé»è®¤å¼ |
| | | * |
| | | * @param name åæ°å |
| | | * @param defaultValue é»è®¤å¼ |
| | | * @return 忰弿é»è®¤å¼ |
| | | */ |
| | | public static Integer getParameterToInt(String name, Integer defaultValue) { |
| | | return Convert.toInt(getRequest().getParameter(name), defaultValue); |
| | | } |
| | | |
| | | /** |
| | | * è·åæå®åç§°ç Boolean ç±»åç请æ±åæ° |
| | | * |
| | | * @param name åæ°å |
| | | * @return åæ°å¼ |
| | | */ |
| | | public static Boolean getParameterToBool(String name) { |
| | | return Convert.toBool(getRequest().getParameter(name)); |
| | | } |
| | | |
| | | /** |
| | | * è·åæå®åç§°ç Boolean ç±»åç请æ±åæ°ï¼è¥åæ°ä¸åå¨ï¼åè¿åé»è®¤å¼ |
| | | * |
| | | * @param name åæ°å |
| | | * @param defaultValue é»è®¤å¼ |
| | | * @return 忰弿é»è®¤å¼ |
| | | */ |
| | | public static Boolean getParameterToBool(String name, Boolean defaultValue) { |
| | | return Convert.toBool(getRequest().getParameter(name), defaultValue); |
| | | } |
| | | |
| | | /** |
| | | * è·åææè¯·æ±åæ°ï¼ä»¥ Map çå½¢å¼è¿åï¼ |
| | | * |
| | | * @param request 请æ±å¯¹è±¡{@link ServletRequest} |
| | | * @return 请æ±åæ°ç Mapï¼é®ä¸ºåæ°åï¼å¼ä¸ºåæ°å¼æ°ç» |
| | | */ |
| | | public static Map<String, String[]> getParams(ServletRequest request) { |
| | | final Map<String, String[]> map = request.getParameterMap(); |
| | | return Collections.unmodifiableMap(map); |
| | | } |
| | | |
| | | /** |
| | | * è·åææè¯·æ±åæ°ï¼ä»¥ Map çå½¢å¼è¿åï¼å¼ä¸ºå符串形å¼çæ¼æ¥ï¼ |
| | | * |
| | | * @param request 请æ±å¯¹è±¡{@link ServletRequest} |
| | | * @return 请æ±åæ°ç Mapï¼é®ä¸ºåæ°åï¼å¼ä¸ºæ¼æ¥åçå符串 |
| | | */ |
| | | public static Map<String, String> getParamMap(ServletRequest request) { |
| | | Map<String, String> params = new HashMap<>(); |
| | | for (Map.Entry<String, String[]> entry : getParams(request).entrySet()) { |
| | | params.put(entry.getKey(), StringUtils.joinComma(entry.getValue())); |
| | | } |
| | | return params; |
| | | } |
| | | |
| | | /** |
| | | * è·åå½å HTTP 请æ±å¯¹è±¡ |
| | | * |
| | | * @return å½å HTTP 请æ±å¯¹è±¡ |
| | | */ |
| | | public static HttpServletRequest getRequest() { |
| | | try { |
| | | return getRequestAttributes().getRequest(); |
| | | } catch (Exception e) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è·åå½å HTTP ååºå¯¹è±¡ |
| | | * |
| | | * @return å½å HTTP ååºå¯¹è±¡ |
| | | */ |
| | | public static HttpServletResponse getResponse() { |
| | | try { |
| | | return getRequestAttributes().getResponse(); |
| | | } catch (Exception e) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è·åå½å请æ±ç HttpSession 对象 |
| | | * <p> |
| | | * 妿å½å请æ±å·²ç»å
³èäºä¸ä¸ªä¼è¯ï¼å³å·²ç»å卿æç session IDï¼ï¼ |
| | | * åè¿å该ä¼è¯å¯¹è±¡ï¼å¦ææ²¡æå
³èä¼è¯ï¼åä¼å建ä¸ä¸ªæ°çä¼è¯å¯¹è±¡å¹¶è¿åã |
| | | * <p> |
| | | * HttpSession ç¨äºåå¨ä¼è¯çº§å«çæ°æ®ï¼å¦ç¨æ·ç»å½ä¿¡æ¯ãè´ç©è½¦å
容çï¼ |
| | | * å¯ä»¥å¨å¤ä¸ªè¯·æ±ä¹é´å
±äº«ä¼è¯æ°æ® |
| | | * |
| | | * @return å½å请æ±ç HttpSession 对象 |
| | | */ |
| | | public static HttpSession getSession() { |
| | | return getRequest().getSession(); |
| | | } |
| | | |
| | | /** |
| | | * è·åå½å请æ±ç请æ±å±æ§ |
| | | * |
| | | * @return {@link ServletRequestAttributes} 请æ±å±æ§å¯¹è±¡ |
| | | */ |
| | | public static ServletRequestAttributes getRequestAttributes() { |
| | | try { |
| | | RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); |
| | | return (ServletRequestAttributes) attributes; |
| | | } catch (Exception e) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è·åæå®è¯·æ±å¤´çå¼ï¼å¦æå¤´é¨ä¸ºç©ºåè¿å空å符串 |
| | | * |
| | | * @param request 请æ±å¯¹è±¡ |
| | | * @param name 头é¨åç§° |
| | | * @return 头é¨å¼ |
| | | */ |
| | | public static String getHeader(HttpServletRequest request, String name) { |
| | | String value = request.getHeader(name); |
| | | if (StringUtils.isEmpty(value)) { |
| | | return StringUtils.EMPTY; |
| | | } |
| | | return urlDecode(value); |
| | | } |
| | | |
| | | /** |
| | | * è·åææè¯·æ±å¤´ç Mapï¼é®ä¸ºå¤´é¨åç§°ï¼å¼ä¸ºå¤´é¨å¼ |
| | | * |
| | | * @param request 请æ±å¯¹è±¡ |
| | | * @return 请æ±å¤´ç Map |
| | | */ |
| | | public static Map<String, String> getHeaders(HttpServletRequest request) { |
| | | Map<String, String> map = new LinkedCaseInsensitiveMap<>(); |
| | | Enumeration<String> enumeration = request.getHeaderNames(); |
| | | if (enumeration != null) { |
| | | while (enumeration.hasMoreElements()) { |
| | | String key = enumeration.nextElement(); |
| | | String value = request.getHeader(key); |
| | | map.put(key, value); |
| | | } |
| | | } |
| | | return map; |
| | | } |
| | | |
| | | /** |
| | | * å°å符串渲æå°å®¢æ·ç«¯ï¼ä»¥ JSON æ ¼å¼è¿åï¼ |
| | | * |
| | | * @param response 渲æå¯¹è±¡ |
| | | * @param string å¾
渲æçå符串 |
| | | */ |
| | | public static void renderString(HttpServletResponse response, String string) { |
| | | try { |
| | | response.setStatus(HttpStatus.HTTP_OK); |
| | | response.setContentType(MediaType.APPLICATION_JSON_VALUE); |
| | | response.setCharacterEncoding(StandardCharsets.UTF_8.toString()); |
| | | response.getWriter().print(string); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 夿å½åè¯·æ±æ¯å¦ä¸º Ajax 弿¥è¯·æ± |
| | | * |
| | | * @param request 请æ±å¯¹è±¡ |
| | | * @return æ¯å¦ä¸º Ajax è¯·æ± |
| | | */ |
| | | public static boolean isAjaxRequest(HttpServletRequest request) { |
| | | |
| | | // 夿 Accept 头鍿¯å¦å
å« application/json |
| | | String accept = request.getHeader("accept"); |
| | | if (accept != null && accept.contains(MediaType.APPLICATION_JSON_VALUE)) { |
| | | return true; |
| | | } |
| | | |
| | | // 夿 X-Requested-With 头鍿¯å¦å
å« XMLHttpRequest |
| | | String xRequestedWith = request.getHeader("X-Requested-With"); |
| | | if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest")) { |
| | | return true; |
| | | } |
| | | |
| | | // 夿 URI åç¼æ¯å¦ä¸º .json æ .xml |
| | | String uri = request.getRequestURI(); |
| | | if (StringUtils.equalsAnyIgnoreCase(uri, ".json", ".xml")) { |
| | | return true; |
| | | } |
| | | |
| | | // å¤æè¯·æ±åæ° __ajax æ¯å¦ä¸º json æ xml |
| | | String ajax = request.getParameter("__ajax"); |
| | | return StringUtils.equalsAnyIgnoreCase(ajax, "json", "xml"); |
| | | } |
| | | |
| | | /** |
| | | * è·å客æ·ç«¯ IP å°å |
| | | * |
| | | * @return 客æ·ç«¯ IP å°å |
| | | */ |
| | | public static String getClientIP() { |
| | | return getClientIP(getRequest()); |
| | | } |
| | | |
| | | /** |
| | | * 对å
容è¿è¡ URL ç¼ç |
| | | * |
| | | * @param str å
容 |
| | | * @return ç¼ç åçå
容 |
| | | */ |
| | | public static String urlEncode(String str) { |
| | | return URLEncoder.encode(str, StandardCharsets.UTF_8); |
| | | } |
| | | |
| | | /** |
| | | * 对å
容è¿è¡ URL è§£ç |
| | | * |
| | | * @param str å
容 |
| | | * @return è§£ç åçå
容 |
| | | */ |
| | | public static String urlDecode(String str) { |
| | | return URLDecoder.decode(str, StandardCharsets.UTF_8); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils; |
| | | |
| | | import cn.hutool.extra.spring.SpringUtil; |
| | | import org.springframework.beans.factory.NoSuchBeanDefinitionException; |
| | | import org.springframework.boot.autoconfigure.thread.Threading; |
| | | import org.springframework.context.ApplicationContext; |
| | | import org.springframework.core.env.Environment; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | /** |
| | | * springå·¥å
·ç±» |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Component |
| | | public final class SpringUtils extends SpringUtil { |
| | | |
| | | /** |
| | | * 妿BeanFactoryå
å«ä¸ä¸ªä¸æç»åç§°å¹é
çbeanå®ä¹ï¼åè¿åtrue |
| | | */ |
| | | public static boolean containsBean(String name) { |
| | | return getBeanFactory().containsBean(name); |
| | | } |
| | | |
| | | /** |
| | | * 夿以ç»å®ååæ³¨åçbeanå®ä¹æ¯ä¸ä¸ªsingletonè¿æ¯ä¸ä¸ªprototypeã |
| | | * 妿ä¸ç»å®ååç¸åºçbeanå®ä¹æ²¡æè¢«æ¾å°ï¼å°ä¼æåºä¸ä¸ªå¼å¸¸ï¼NoSuchBeanDefinitionExceptionï¼ |
| | | */ |
| | | public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException { |
| | | return getBeanFactory().isSingleton(name); |
| | | } |
| | | |
| | | /** |
| | | * @return Class 注å对象çç±»å |
| | | */ |
| | | public static Class<?> getType(String name) throws NoSuchBeanDefinitionException { |
| | | return getBeanFactory().getType(name); |
| | | } |
| | | |
| | | /** |
| | | * 妿ç»å®çbeanååå¨beanå®ä¹ä¸æå«åï¼åè¿åè¿äºå«å |
| | | */ |
| | | public static String[] getAliases(String name) throws NoSuchBeanDefinitionException { |
| | | return getBeanFactory().getAliases(name); |
| | | } |
| | | |
| | | /** |
| | | * è·åaop代ç对象 |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public static <T> T getAopProxy(T invoker) { |
| | | return (T) getBean(invoker.getClass()); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * è·åspringä¸ä¸æ |
| | | */ |
| | | public static ApplicationContext context() { |
| | | return getApplicationContext(); |
| | | } |
| | | |
| | | public static boolean isVirtual() { |
| | | return Threading.VIRTUAL.isActive(getBean(Environment.class)); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.map.MapUtil; |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.util.*; |
| | | import java.util.function.BiFunction; |
| | | import java.util.function.Function; |
| | | import java.util.function.Predicate; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * stream æµå·¥å
·ç±» |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE) |
| | | public class StreamUtils { |
| | | |
| | | /** |
| | | * å°collectionè¿æ»¤ |
| | | * |
| | | * @param collection éè¦è½¬åçéå |
| | | * @param function è¿æ»¤æ¹æ³ |
| | | * @return è¿æ»¤åçlist |
| | | */ |
| | | public static <E> List<E> filter(Collection<E> collection, Predicate<E> function) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return CollUtil.newArrayList(); |
| | | } |
| | | return collection.stream() |
| | | .filter(function) |
| | | // æ³¨ææ¤å¤ä¸è¦ä½¿ç¨ .toList() æ°è¯æ³ å 为è¿åçæ¯ä¸å¯åList ä¼å¯¼è´åºååé®é¢ |
| | | .collect(Collectors.toList()); |
| | | } |
| | | |
| | | /** |
| | | * æ¾å°æµä¸æ»¡è¶³æ¡ä»¶ç第ä¸ä¸ªå
ç´ |
| | | * |
| | | * @param collection éè¦æ¥è¯¢çéå |
| | | * @param function è¿æ»¤æ¹æ³ |
| | | * @return æ¾å°ç¬¦åæ¡ä»¶ç第ä¸ä¸ªå
ç´ ï¼æ²¡æåè¿å Optional.empty() |
| | | */ |
| | | public static <E> Optional<E> findFirst(Collection<E> collection, Predicate<E> function) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return Optional.empty(); |
| | | } |
| | | return collection.stream() |
| | | .filter(function) |
| | | .findFirst(); |
| | | } |
| | | |
| | | /** |
| | | * æ¾å°æµä¸æ»¡è¶³æ¡ä»¶ç第ä¸ä¸ªå
ç´ å¼ |
| | | * |
| | | * @param collection éè¦æ¥è¯¢çéå |
| | | * @param function è¿æ»¤æ¹æ³ |
| | | * @return æ¾å°ç¬¦åæ¡ä»¶ç第ä¸ä¸ªå
ç´ ï¼æ²¡æåè¿å null |
| | | */ |
| | | public static <E> E findFirstValue(Collection<E> collection, Predicate<E> function) { |
| | | return findFirst(collection,function).orElse(null); |
| | | } |
| | | |
| | | /** |
| | | * æ¾å°æµä¸ä»»æä¸ä¸ªæ»¡è¶³æ¡ä»¶çå
ç´ |
| | | * |
| | | * @param collection éè¦æ¥è¯¢çéå |
| | | * @param function è¿æ»¤æ¹æ³ |
| | | * @return æ¾å°ç¬¦åæ¡ä»¶çä»»æä¸ä¸ªå
ç´ ï¼æ²¡æåè¿å Optional.empty() |
| | | */ |
| | | public static <E> Optional<E> findAny(Collection<E> collection, Predicate<E> function) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return Optional.empty(); |
| | | } |
| | | return collection.stream() |
| | | .filter(function) |
| | | .findAny(); |
| | | } |
| | | |
| | | /** |
| | | * æ¾å°æµä¸ä»»æä¸ä¸ªæ»¡è¶³æ¡ä»¶çå
ç´ å¼ |
| | | * |
| | | * @param collection éè¦æ¥è¯¢çéå |
| | | * @param function è¿æ»¤æ¹æ³ |
| | | * @return æ¾å°ç¬¦åæ¡ä»¶çä»»æä¸ä¸ªå
ç´ ï¼æ²¡æåè¿ånull |
| | | */ |
| | | public static <E> E findAnyValue(Collection<E> collection, Predicate<E> function) { |
| | | return findAny(collection,function).orElse(null); |
| | | } |
| | | |
| | | /** |
| | | * å°collectionæ¼æ¥ |
| | | * |
| | | * @param collection éè¦è½¬åçéå |
| | | * @param function æ¼æ¥æ¹æ³ |
| | | * @return æ¼æ¥åçlist |
| | | */ |
| | | public static <E> String join(Collection<E> collection, Function<E, String> function) { |
| | | return join(collection, function, StringUtils.SEPARATOR); |
| | | } |
| | | |
| | | /** |
| | | * å°collectionæ¼æ¥ |
| | | * |
| | | * @param collection éè¦è½¬åçéå |
| | | * @param function æ¼æ¥æ¹æ³ |
| | | * @param delimiter æ¼æ¥ç¬¦ |
| | | * @return æ¼æ¥åçlist |
| | | */ |
| | | public static <E> String join(Collection<E> collection, Function<E, String> function, CharSequence delimiter) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return StringUtils.EMPTY; |
| | | } |
| | | return collection.stream() |
| | | .map(function) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.joining(delimiter)); |
| | | } |
| | | |
| | | /** |
| | | * å°collectionæåº |
| | | * |
| | | * @param collection éè¦è½¬åçéå |
| | | * @param comparing æåºæ¹æ³ |
| | | * @return æåºåçlist |
| | | */ |
| | | public static <E> List<E> sorted(Collection<E> collection, Comparator<E> comparing) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return CollUtil.newArrayList(); |
| | | } |
| | | return collection.stream() |
| | | .filter(Objects::nonNull) |
| | | .sorted(comparing) |
| | | // æ³¨ææ¤å¤ä¸è¦ä½¿ç¨ .toList() æ°è¯æ³ å 为è¿åçæ¯ä¸å¯åList ä¼å¯¼è´åºååé®é¢ |
| | | .collect(Collectors.toList()); |
| | | } |
| | | |
| | | /** |
| | | * å°collection转å为类åä¸åçmap<br> |
| | | * <B>{@code Collection<V> ----> Map<K,V>}</B> |
| | | * |
| | | * @param collection éè¦è½¬åçéå |
| | | * @param key Vç±»å转å为Kç±»åçlambdaæ¹æ³ |
| | | * @param <V> collectionä¸çæ³å |
| | | * @param <K> mapä¸çkeyç±»å |
| | | * @return 转ååçmap |
| | | */ |
| | | public static <V, K> Map<K, V> toIdentityMap(Collection<V> collection, Function<V, K> key) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return MapUtil.newHashMap(); |
| | | } |
| | | return collection.stream() |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toMap(key, Function.identity(), (l, r) -> l)); |
| | | } |
| | | |
| | | /** |
| | | * å°Collection转å为map(valueç±»åä¸collectionçæ³åä¸å)<br> |
| | | * <B>{@code Collection<E> -----> Map<K,V> }</B> |
| | | * |
| | | * @param collection éè¦è½¬åçéå |
| | | * @param key Eç±»å转å为Kç±»åçlambdaæ¹æ³ |
| | | * @param value Eç±»å转å为Vç±»åçlambdaæ¹æ³ |
| | | * @param <E> collectionä¸çæ³å |
| | | * @param <K> mapä¸çkeyç±»å |
| | | * @param <V> mapä¸çvalueç±»å |
| | | * @return 转ååçmap |
| | | */ |
| | | public static <E, K, V> Map<K, V> toMap(Collection<E> collection, Function<E, K> key, Function<E, V> value) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return MapUtil.newHashMap(); |
| | | } |
| | | return collection.stream() |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toMap(key, value, (l, r) -> l)); |
| | | } |
| | | |
| | | /** |
| | | * è·å map ä¸çæ°æ®ä½ä¸ºæ° Map ç value ï¼key ä¸å |
| | | * @param map éè¦å¤ççmap |
| | | * @param take åå¼å½æ° |
| | | * @param <K> mapä¸çkeyç±»å |
| | | * @param <E> mapä¸çvalueç±»å |
| | | * @param <V> æ°mapä¸çvalueç±»å |
| | | * @return æ°çmap |
| | | */ |
| | | public static <K, E, V> Map<K, V> toMap(Map<K, E> map, BiFunction<K, E, V> take) { |
| | | if (CollUtil.isEmpty(map)) { |
| | | return MapUtil.newHashMap(); |
| | | } |
| | | return toMap(map.entrySet(), Map.Entry::getKey, entry -> take.apply(entry.getKey(), entry.getValue())); |
| | | } |
| | | |
| | | /** |
| | | * å°collectionæç
§è§å(æ¯å¦æç¸åçç级id)åç±»æmap<br> |
| | | * <B>{@code Collection<E> -------> Map<K,List<E>> } </B> |
| | | * |
| | | * @param collection éè¦åç±»çéå |
| | | * @param key åç±»çè§å |
| | | * @param <E> collectionä¸çæ³å |
| | | * @param <K> mapä¸çkeyç±»å |
| | | * @return åç±»åçmap |
| | | */ |
| | | public static <E, K> Map<K, List<E>> groupByKey(Collection<E> collection, Function<E, K> key) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return MapUtil.newHashMap(); |
| | | } |
| | | return collection.stream() |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.groupingBy(key, LinkedHashMap::new, Collectors.toList())); |
| | | } |
| | | |
| | | /** |
| | | * å°collectionæç
§ä¸¤ä¸ªè§å(æ¯å¦æç¸åç年级id,ç级id)åç±»æåå±map<br> |
| | | * <B>{@code Collection<E> ---> Map<T,Map<U,List<E>>> } </B> |
| | | * |
| | | * @param collection éè¦åç±»çéå |
| | | * @param key1 第ä¸ä¸ªåç±»çè§å |
| | | * @param key2 第äºä¸ªåç±»çè§å |
| | | * @param <E> éåå
ç´ ç±»å |
| | | * @param <K> 第ä¸ä¸ªmapä¸çkeyç±»å |
| | | * @param <U> 第äºä¸ªmapä¸çkeyç±»å |
| | | * @return åç±»åçmap |
| | | */ |
| | | public static <E, K, U> Map<K, Map<U, List<E>>> groupBy2Key(Collection<E> collection, Function<E, K> key1, Function<E, U> key2) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return MapUtil.newHashMap(); |
| | | } |
| | | return collection.stream() |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.groupingBy(key2, LinkedHashMap::new, Collectors.toList()))); |
| | | } |
| | | |
| | | /** |
| | | * å°collectionæç
§ä¸¤ä¸ªè§å(æ¯å¦æç¸åç年级id,ç级id)åç±»æåå±map<br> |
| | | * <B>{@code Collection<E> ---> Map<T,Map<U,E>> } </B> |
| | | * |
| | | * @param collection éè¦åç±»çéå |
| | | * @param key1 第ä¸ä¸ªåç±»çè§å |
| | | * @param key2 第äºä¸ªåç±»çè§å |
| | | * @param <T> 第ä¸ä¸ªmapä¸çkeyç±»å |
| | | * @param <U> 第äºä¸ªmapä¸çkeyç±»å |
| | | * @param <E> collectionä¸çæ³å |
| | | * @return åç±»åçmap |
| | | */ |
| | | public static <E, T, U> Map<T, Map<U, E>> group2Map(Collection<E> collection, Function<E, T> key1, Function<E, U> key2) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return MapUtil.newHashMap(); |
| | | } |
| | | return collection.stream() |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.toMap(key2, Function.identity(), (l, r) -> l))); |
| | | } |
| | | |
| | | /** |
| | | * å°collection转å为Listéåï¼ä½æ¯ä¸¤è
çæ³åä¸å<br> |
| | | * <B>{@code Collection<E> ------> List<T> } </B> |
| | | * |
| | | * @param collection éè¦è½¬åçéå |
| | | * @param function collectionä¸çæ³å转å为listæ³åçlambdaè¡¨è¾¾å¼ |
| | | * @param <E> collectionä¸çæ³å |
| | | * @param <T> Listä¸çæ³å |
| | | * @return 转ååçlist |
| | | */ |
| | | public static <E, T> List<T> toList(Collection<E> collection, Function<E, T> function) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return CollUtil.newArrayList(); |
| | | } |
| | | return collection.stream() |
| | | .map(function) |
| | | .filter(Objects::nonNull) |
| | | // æ³¨ææ¤å¤ä¸è¦ä½¿ç¨ .toList() æ°è¯æ³ å 为è¿åçæ¯ä¸å¯åList ä¼å¯¼è´åºååé®é¢ |
| | | .collect(Collectors.toList()); |
| | | } |
| | | |
| | | /** |
| | | * å°collection转å为Setéåï¼ä½æ¯ä¸¤è
çæ³åä¸å<br> |
| | | * <B>{@code Collection<E> ------> Set<T> } </B> |
| | | * |
| | | * @param collection éè¦è½¬åçéå |
| | | * @param function collectionä¸çæ³å转å为setæ³åçlambdaè¡¨è¾¾å¼ |
| | | * @param <E> collectionä¸çæ³å |
| | | * @param <T> Setä¸çæ³å |
| | | * @return 转ååçSet |
| | | */ |
| | | public static <E, T> Set<T> toSet(Collection<E> collection, Function<E, T> function) { |
| | | if (CollUtil.isEmpty(collection)) { |
| | | return CollUtil.newHashSet(); |
| | | } |
| | | return collection.stream() |
| | | .map(function) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toSet()); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * å并两个ç¸åkeyç±»åçmap |
| | | * |
| | | * @param map1 第ä¸ä¸ªéè¦åå¹¶ç map |
| | | * @param map2 第äºä¸ªéè¦åå¹¶ç map |
| | | * @param merge åå¹¶çlambdaï¼å°key value1 value2åå¹¶ææç»çç±»å,注ævalueå¯è½ä¸ºç©ºçæ
åµ |
| | | * @param <K> mapä¸çkeyç±»å |
| | | * @param <X> 第ä¸ä¸ª mapçvalueç±»å |
| | | * @param <Y> 第äºä¸ª mapçvalueç±»å |
| | | * @param <V> æç»mapçvalueç±»å |
| | | * @return åå¹¶åçmap |
| | | */ |
| | | public static <K, X, Y, V> Map<K, V> merge(Map<K, X> map1, Map<K, Y> map2, BiFunction<X, Y, V> merge) { |
| | | if (CollUtil.isEmpty(map1) && CollUtil.isEmpty(map2)) { |
| | | // å¦æä¸¤ä¸ª map é½ä¸ºç©ºï¼åç´æ¥è¿å空ç map |
| | | return MapUtil.newHashMap(); |
| | | } else if (CollUtil.isEmpty(map1)) { |
| | | // 妿 map1 为空ï¼åç´æ¥å¤çè¿å map2 |
| | | return toMap(map2.entrySet(), Map.Entry::getKey, entry -> merge.apply(null, entry.getValue())); |
| | | } else if (CollUtil.isEmpty(map2)) { |
| | | // 妿 map2 为空ï¼åç´æ¥å¤çè¿å map1 |
| | | return toMap(map1.entrySet(), Map.Entry::getKey, entry -> merge.apply(entry.getValue(), null)); |
| | | } |
| | | Set<K> keySet = new HashSet<>(); |
| | | keySet.addAll(map1.keySet()); |
| | | keySet.addAll(map2.keySet()); |
| | | return toMap(keySet, key -> key, key -> merge.apply(map1.get(key), map2.get(key))); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.lang.Validator; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import org.springframework.util.AntPathMatcher; |
| | | |
| | | import java.nio.charset.Charset; |
| | | import java.util.*; |
| | | import java.util.function.Function; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * å符串工å
·ç±» |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public class StringUtils extends org.apache.commons.lang3.StringUtils { |
| | | |
| | | public static final String SEPARATOR = ","; |
| | | |
| | | public static final String SLASH = "/"; |
| | | |
| | | @Deprecated |
| | | private StringUtils() { |
| | | } |
| | | |
| | | /** |
| | | * è·ååæ°ä¸ä¸ºç©ºå¼ |
| | | * |
| | | * @param str defaultValue è¦å¤æçvalue |
| | | * @return value è¿åå¼ |
| | | */ |
| | | public static String blankToDefault(String str, String defaultValue) { |
| | | return StrUtil.blankToDefault(str, defaultValue); |
| | | } |
| | | |
| | | /** |
| | | * * 夿ä¸ä¸ªå符串æ¯å¦ä¸ºç©ºä¸² |
| | | * |
| | | * @param str String |
| | | * @return trueï¼ä¸ºç©º falseï¼é空 |
| | | */ |
| | | public static boolean isEmpty(String str) { |
| | | return StrUtil.isEmpty(str); |
| | | } |
| | | |
| | | /** |
| | | * * 夿ä¸ä¸ªå符串æ¯å¦ä¸ºé空串 |
| | | * |
| | | * @param str String |
| | | * @return trueï¼é空串 falseï¼ç©ºä¸² |
| | | */ |
| | | public static boolean isNotEmpty(String str) { |
| | | return !isEmpty(str); |
| | | } |
| | | |
| | | /** |
| | | * å»ç©ºæ ¼ |
| | | */ |
| | | public static String trim(String str) { |
| | | return StrUtil.trim(str); |
| | | } |
| | | |
| | | /** |
| | | * æªåå符串 |
| | | * |
| | | * @param str å符串 |
| | | * @param start å¼å§ |
| | | * @return ç»æ |
| | | */ |
| | | public static String substring(final String str, int start) { |
| | | return substring(str, start, str.length()); |
| | | } |
| | | |
| | | /** |
| | | * æªåå符串 |
| | | * |
| | | * @param str å符串 |
| | | * @param start å¼å§ |
| | | * @param end ç»æ |
| | | * @return ç»æ |
| | | */ |
| | | public static String substring(final String str, int start, int end) { |
| | | return StrUtil.sub(str, start, end); |
| | | } |
| | | |
| | | /** |
| | | * æ ¼å¼åææ¬, {} 表示å ä½ç¬¦<br> |
| | | * æ¤æ¹æ³åªæ¯ç®åå°å ä½ç¬¦ {} æç
§é¡ºåºæ¿æ¢ä¸ºåæ°<br> |
| | | * 妿æ³è¾åº {} ä½¿ç¨ \\è½¬ä¹ { å³å¯ï¼å¦ææ³è¾åº {} ä¹åç \ 使ç¨å转ä¹ç¬¦ \\\\ å³å¯<br> |
| | | * ä¾ï¼<br> |
| | | * é常使ç¨ï¼format("this is {} for {}", "a", "b") -> this is a for b<br> |
| | | * 转ä¹{}ï¼ format("this is \\{} for {}", "a", "b") -> this is {} for a<br> |
| | | * 转ä¹\ï¼ format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br> |
| | | * |
| | | * @param template ææ¬æ¨¡æ¿ï¼è¢«æ¿æ¢çé¨åç¨ {} 表示 |
| | | * @param params åæ°å¼ |
| | | * @return æ ¼å¼ååçææ¬ |
| | | */ |
| | | public static String format(String template, Object... params) { |
| | | return StrUtil.format(template, params); |
| | | } |
| | | |
| | | /** |
| | | * æ¯å¦ä¸ºhttp(s)://å¼å¤´ |
| | | * |
| | | * @param link 龿¥ |
| | | * @return ç»æ |
| | | */ |
| | | public static boolean ishttp(String link) { |
| | | return Validator.isUrl(link); |
| | | } |
| | | |
| | | /** |
| | | * å符串转set |
| | | * |
| | | * @param str å符串 |
| | | * @param sep åé符 |
| | | * @return setéå |
| | | */ |
| | | public static Set<String> str2Set(String str, String sep) { |
| | | return new HashSet<>(str2List(str, sep, true, false)); |
| | | } |
| | | |
| | | /** |
| | | * å符串转list |
| | | * |
| | | * @param str å符串 |
| | | * @param sep åé符 |
| | | * @param filterBlank è¿æ»¤çº¯ç©ºç½ |
| | | * @param trim 廿é¦å°¾ç©ºç½ |
| | | * @return listéå |
| | | */ |
| | | public static List<String> str2List(String str, String sep, boolean filterBlank, boolean trim) { |
| | | List<String> list = new ArrayList<>(); |
| | | if (isEmpty(str)) { |
| | | return list; |
| | | } |
| | | |
| | | // è¿æ»¤ç©ºç½å符串 |
| | | if (filterBlank && isBlank(str)) { |
| | | return list; |
| | | } |
| | | String[] split = str.split(sep); |
| | | for (String string : split) { |
| | | if (filterBlank && isBlank(string)) { |
| | | continue; |
| | | } |
| | | if (trim) { |
| | | string = trim(string); |
| | | } |
| | | list.add(string); |
| | | } |
| | | |
| | | return list; |
| | | } |
| | | |
| | | /** |
| | | * æ¥æ¾æå®å符串æ¯å¦å
嫿å®å符串å表ä¸çä»»æä¸ä¸ªåç¬¦ä¸²åæ¶ä¸²å¿½ç¥å¤§å°å |
| | | * |
| | | * @param cs æå®å符串 |
| | | * @param searchCharSequences éè¦æ£æ¥çå符串æ°ç» |
| | | * @return æ¯å¦å
å«ä»»æä¸ä¸ªå符串 |
| | | */ |
| | | public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) { |
| | | return StrUtil.containsAnyIgnoreCase(cs, searchCharSequences); |
| | | } |
| | | |
| | | /** |
| | | * 驼峰转ä¸å线å½å |
| | | */ |
| | | public static String toUnderScoreCase(String str) { |
| | | return StrUtil.toUnderlineCase(str); |
| | | } |
| | | |
| | | /** |
| | | * æ¯å¦å
å«å符串 |
| | | * |
| | | * @param str éªè¯å符串 |
| | | * @param strs åç¬¦ä¸²ç» |
| | | * @return å
å«è¿åtrue |
| | | */ |
| | | public static boolean inStringIgnoreCase(String str, String... strs) { |
| | | return StrUtil.equalsAnyIgnoreCase(str, strs); |
| | | } |
| | | |
| | | /** |
| | | * å°ä¸åçº¿å¤§åæ¹å¼å½åçå符串转æ¢ä¸ºé©¼å³°å¼ãå¦æè½¬æ¢åçä¸åçº¿å¤§åæ¹å¼å½åçå符串为空ï¼åè¿å空å符串ã ä¾å¦ï¼HELLO_WORLD->HelloWorld |
| | | * |
| | | * @param name 转æ¢åçä¸åçº¿å¤§åæ¹å¼å½åçå符串 |
| | | * @return 转æ¢åç驼峰å¼å½åçå符串 |
| | | */ |
| | | public static String convertToCamelCase(String name) { |
| | | return StrUtil.upperFirst(StrUtil.toCamelCase(name)); |
| | | } |
| | | |
| | | /** |
| | | * 驼峰å¼å½åæ³ ä¾å¦ï¼user_name->userName |
| | | */ |
| | | public static String toCamelCase(String s) { |
| | | return StrUtil.toCamelCase(s); |
| | | } |
| | | |
| | | /** |
| | | * æ¥æ¾æå®å符串æ¯å¦å¹é
æå®å符串å表ä¸çä»»æä¸ä¸ªå符串 |
| | | * |
| | | * @param str æå®å符串 |
| | | * @param strs éè¦æ£æ¥çå符串æ°ç» |
| | | * @return æ¯å¦å¹é
|
| | | */ |
| | | public static boolean matches(String str, List<String> strs) { |
| | | if (isEmpty(str) || CollUtil.isEmpty(strs)) { |
| | | return false; |
| | | } |
| | | for (String pattern : strs) { |
| | | if (isMatch(pattern, str)) { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * 夿urlæ¯å¦ä¸è§åé
ç½®: |
| | | * ? 表示å个å符; |
| | | * * 表示ä¸å±è·¯å¾å
çä»»æå符串ï¼ä¸å¯è·¨å±çº§; |
| | | * ** 表示任æå±è·¯å¾; |
| | | * |
| | | * @param pattern å¹é
è§å |
| | | * @param url éè¦å¹é
çurl |
| | | */ |
| | | public static boolean isMatch(String pattern, String url) { |
| | | AntPathMatcher matcher = new AntPathMatcher(); |
| | | return matcher.match(pattern, url); |
| | | } |
| | | |
| | | /** |
| | | * æ°å左边补é½0ï¼ä½¿ä¹è¾¾å°æå®é¿åº¦ã注æï¼å¦ææ°å转æ¢ä¸ºå符串åï¼é¿åº¦å¤§äºsizeï¼ååªä¿ç æåsize个å符ã |
| | | * |
| | | * @param num æ°å对象 |
| | | * @param size å符串æå®é¿åº¦ |
| | | * @return è¿åæ°åçåç¬¦ä¸²æ ¼å¼ï¼è¯¥å符串为æå®é¿åº¦ã |
| | | */ |
| | | public static String padl(final Number num, final int size) { |
| | | return padl(num.toString(), size, '0'); |
| | | } |
| | | |
| | | /** |
| | | * å符串左补é½ã妿åå§å符串sé¿åº¦å¤§äºsizeï¼ååªä¿çæåsize个å符ã |
| | | * |
| | | * @param s åå§å符串 |
| | | * @param size å符串æå®é¿åº¦ |
| | | * @param c ç¨äºè¡¥é½çå符 |
| | | * @return è¿åæå®é¿åº¦çå符串ï¼ç±ååç¬¦ä¸²å·¦è¡¥é½ææªåå¾å°ã |
| | | */ |
| | | public static String padl(final String s, final int size, final char c) { |
| | | final StringBuilder sb = new StringBuilder(size); |
| | | if (s != null) { |
| | | final int len = s.length(); |
| | | if (s.length() <= size) { |
| | | sb.append(Convert.toStr(c).repeat(size - len)); |
| | | sb.append(s); |
| | | } else { |
| | | return s.substring(len - size, len); |
| | | } |
| | | } else { |
| | | sb.append(Convert.toStr(c).repeat(Math.max(0, size))); |
| | | } |
| | | return sb.toString(); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串(åé符é»è®¤éå·) |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @return åå²åçæ°æ®å表 |
| | | */ |
| | | public static List<String> splitList(String str) { |
| | | return splitTo(str, Convert::toStr); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串 |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param separator åé符 |
| | | * @return åå²åçæ°æ®å表 |
| | | */ |
| | | public static List<String> splitList(String str, String separator) { |
| | | return splitTo(str, separator, Convert::toStr); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串èªå®ä¹è½¬æ¢(åé符é»è®¤éå·) |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param mapper èªå®ä¹è½¬æ¢ |
| | | * @return åå²åçæ°æ®å表 |
| | | */ |
| | | public static <T> List<T> splitTo(String str, Function<? super Object, T> mapper) { |
| | | return splitTo(str, SEPARATOR, mapper); |
| | | } |
| | | |
| | | /** |
| | | * ååå符串èªå®ä¹è½¬æ¢ |
| | | * |
| | | * @param str 被ååçå符串 |
| | | * @param separator åé符 |
| | | * @param mapper èªå®ä¹è½¬æ¢ |
| | | * @return åå²åçæ°æ®å表 |
| | | */ |
| | | public static <T> List<T> splitTo(String str, String separator, Function<? super Object, T> mapper) { |
| | | if (isBlank(str)) { |
| | | return new ArrayList<>(0); |
| | | } |
| | | return StrUtil.split(str, separator) |
| | | .stream() |
| | | .filter(Objects::nonNull) |
| | | .map(mapper) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toList()); |
| | | } |
| | | |
| | | /** |
| | | * ä¸åºå大å°åæ£æ¥ CharSequence æ¯å¦ä»¥æå®çåç¼å¼å¤´ã |
| | | * |
| | | * @param str è¦æ£æ¥ç CharSequence å¯è½ä¸º null |
| | | * @param prefixs è¦æ¥æ¾çåç¼å¯è½ä¸º null |
| | | * @return æ¯å¦å
å« |
| | | */ |
| | | public static boolean startWithAnyIgnoreCase(CharSequence str, CharSequence... prefixs) { |
| | | // 夿æ¯å¦æ¯ä»¥æå®å符串å¼å¤´ |
| | | for (CharSequence prefix : prefixs) { |
| | | if (StringUtils.startsWithIgnoreCase(str, prefix)) { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * å°åç¬¦ä¸²ä»æºå符é转æ¢ä¸ºç®æ å符é |
| | | * |
| | | * @param input åå§å符串 |
| | | * @param fromCharset æºå符é |
| | | * @param toCharset ç®æ å符é |
| | | * @return 转æ¢åçå符串 |
| | | */ |
| | | public static String convert(String input, Charset fromCharset, Charset toCharset) { |
| | | if (isBlank(input)) { |
| | | return input; |
| | | } |
| | | try { |
| | | // 仿ºå符éè·ååè |
| | | byte[] bytes = input.getBytes(fromCharset); |
| | | // 使ç¨ç®æ å符éè§£ç |
| | | return new String(bytes, toCharset); |
| | | } catch (Exception e) { |
| | | return input; |
| | | } |
| | | } |
| | | /** |
| | | * å°å¯è¿ä»£å¯¹è±¡ä¸çå
ç´ ä½¿ç¨éå·æ¼æ¥æå符串 |
| | | * |
| | | * @param iterable å¯è¿ä»£å¯¹è±¡ï¼å¦ ListãSet ç |
| | | * @return æ¼æ¥åçå符串 |
| | | */ |
| | | public static String joinComma(Iterable<?> iterable) { |
| | | return StringUtils.join(iterable, SEPARATOR); |
| | | } |
| | | |
| | | /** |
| | | * å°æ°ç»ä¸çå
ç´ ä½¿ç¨éå·æ¼æ¥æå符串 |
| | | * |
| | | * @param array ä»»æç±»åçæ°ç» |
| | | * @return æ¼æ¥åçå符串 |
| | | */ |
| | | public static String joinComma(Object[] array) { |
| | | return StringUtils.join(array, SEPARATOR); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.lang.tree.Tree; |
| | | import cn.hutool.core.lang.tree.TreeNodeConfig; |
| | | import cn.hutool.core.lang.tree.TreeUtil; |
| | | import cn.hutool.core.lang.tree.parser.NodeParser; |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | import org.dromara.common.core.utils.reflect.ReflectUtils; |
| | | |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.util.function.Function; |
| | | import java.util.stream.Collectors; |
| | | import java.util.stream.Stream; |
| | | |
| | | /** |
| | | * æ©å± hutool TreeUtil å°è£
ç³»ç»æ æå»º |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE) |
| | | public class TreeBuildUtils extends TreeUtil { |
| | | |
| | | /** |
| | | * æ ¹æ®å端å®å¶å·®å¼ååæ®µ |
| | | */ |
| | | public static final TreeNodeConfig DEFAULT_CONFIG = TreeNodeConfig.DEFAULT_CONFIG.setNameKey("label"); |
| | | |
| | | /** |
| | | * æå»ºæ å½¢ç»æ |
| | | * |
| | | * @param <T> è¾å
¥èç¹çç±»å |
| | | * @param <K> èç¹IDçç±»å |
| | | * @param list èç¹å表ï¼å
¶ä¸å
å«äºè¦æå»ºæ å½¢ç»æçææèç¹ |
| | | * @param nodeParser è§£æå¨ï¼ç¨äºå°è¾å
¥èç¹è½¬æ¢ä¸ºæ èç¹ |
| | | * @return æå»ºå¥½çæ å½¢ç»æå表 |
| | | */ |
| | | public static <T, K> List<Tree<K>> build(List<T> list, NodeParser<T, K> nodeParser) { |
| | | if (CollUtil.isEmpty(list)) { |
| | | return CollUtil.newArrayList(); |
| | | } |
| | | K k = ReflectUtils.invokeGetter(list.get(0), "parentId"); |
| | | return TreeUtil.build(list, k, DEFAULT_CONFIG, nodeParser); |
| | | } |
| | | |
| | | /** |
| | | * æå»ºæ å½¢ç»æ |
| | | * |
| | | * @param <T> è¾å
¥èç¹çç±»å |
| | | * @param <K> èç¹IDçç±»å |
| | | * @param parentId 顶级èç¹ |
| | | * @param list èç¹å表ï¼å
¶ä¸å
å«äºè¦æå»ºæ å½¢ç»æçææèç¹ |
| | | * @param nodeParser è§£æå¨ï¼ç¨äºå°è¾å
¥èç¹è½¬æ¢ä¸ºæ èç¹ |
| | | * @return æå»ºå¥½çæ å½¢ç»æå表 |
| | | */ |
| | | public static <T, K> List<Tree<K>> build(List<T> list, K parentId, NodeParser<T, K> nodeParser) { |
| | | if (CollUtil.isEmpty(list)) { |
| | | return CollUtil.newArrayList(); |
| | | } |
| | | return TreeUtil.build(list, parentId, DEFAULT_CONFIG, nodeParser); |
| | | } |
| | | |
| | | /** |
| | | * æå»ºå¤æ ¹èç¹çæ ç»æï¼æ¯æå¤ä¸ªé¡¶çº§èç¹ï¼ |
| | | * |
| | | * @param list åå§æ°æ®å表 |
| | | * @param getId è·åèç¹ ID çæ¹æ³å¼ç¨ï¼ä¾å¦ï¼node -> node.getId() |
| | | * @param getParentId è·åèç¹ç¶çº§ ID çæ¹æ³å¼ç¨ï¼ä¾å¦ï¼node -> node.getParentId() |
| | | * @param parser æ èç¹å±æ§æ å°å¨ï¼ç¨äºå°åå§èç¹ T 转为 Tree èç¹ |
| | | * @param <T> åå§æ°æ®ç±»åï¼å¦å®ä½ç±»ãDTO çï¼ |
| | | * @param <K> èç¹ ID ç±»åï¼å¦ LongãStringï¼ |
| | | * @return æå»ºå®æçæ å½¢ç»æï¼å¯è½å
å«å¤ä¸ªé¡¶çº§æ ¹èç¹ï¼ |
| | | */ |
| | | public static <T, K> List<Tree<K>> buildMultiRoot(List<T> list, Function<T, K> getId, Function<T, K> getParentId, NodeParser<T, K> parser) { |
| | | if (CollUtil.isEmpty(list)) { |
| | | return CollUtil.newArrayList(); |
| | | } |
| | | |
| | | Set<K> rootParentIds = StreamUtils.toSet(list, getParentId); |
| | | rootParentIds.removeAll(StreamUtils.toSet(list, getId)); |
| | | |
| | | // æå»ºæ¯ä¸ä¸ªæ ¹ parentId ä¸çæ ï¼å¹¶åå¹¶ææç»ç»æå表 |
| | | return rootParentIds.stream() |
| | | .flatMap(rootParentId -> TreeUtil.build(list, rootParentId, parser).stream()) |
| | | .collect(Collectors.toList()); |
| | | } |
| | | |
| | | /** |
| | | * è·åèç¹åè¡¨ä¸ææèç¹çå¶åèç¹ |
| | | * |
| | | * @param <K> èç¹IDçç±»å |
| | | * @param nodes èç¹å表 |
| | | * @return å
嫿æå¶åèç¹çå表 |
| | | */ |
| | | public static <K> List<Tree<K>> getLeafNodes(List<Tree<K>> nodes) { |
| | | if (CollUtil.isEmpty(nodes)) { |
| | | return CollUtil.newArrayList(); |
| | | } |
| | | return nodes.stream() |
| | | .flatMap(TreeBuildUtils::extractLeafNodes) |
| | | .collect(Collectors.toList()); |
| | | } |
| | | |
| | | /** |
| | | * è·åæå®èç¹ä¸çææå¶åèç¹ |
| | | * |
| | | * @param <K> èç¹IDçç±»å |
| | | * @param node è¦æ¥æ¾å¶åèç¹çæ ¹èç¹ |
| | | * @return å
嫿æå¶åèç¹çå表 |
| | | */ |
| | | private static <K> Stream<Tree<K>> extractLeafNodes(Tree<K> node) { |
| | | if (!node.hasChild()) { |
| | | return Stream.of(node); |
| | | } else { |
| | | // éå½è°ç¨ï¼è·åææåèç¹çå¶åèç¹ |
| | | return node.getChildren().stream() |
| | | .flatMap(TreeBuildUtils::extractLeafNodes); |
| | | } |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils; |
| | | |
| | | import jakarta.validation.ConstraintViolation; |
| | | import jakarta.validation.ConstraintViolationException; |
| | | import jakarta.validation.Validator; |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * Validator æ ¡éªæ¡æ¶å·¥å
· |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE) |
| | | public class ValidatorUtils { |
| | | |
| | | private static final Validator VALID = SpringUtils.getBean(Validator.class); |
| | | |
| | | /** |
| | | * 对ç»å®å¯¹è±¡è¿è¡åæ°æ ¡éªï¼å¹¶æ ¹æ®æå®çæ ¡éªç»è¿è¡æ ¡éª |
| | | * |
| | | * @param object è¦è¿è¡æ ¡éªç对象 |
| | | * @param groups æ ¡éªç» |
| | | * @throws ConstraintViolationException å¦ææ ¡éªä¸éè¿ï¼åæåºåæ°æ ¡éªå¼å¸¸ |
| | | */ |
| | | public static <T> void validate(T object, Class<?>... groups) { |
| | | Set<ConstraintViolation<T>> validate = VALID.validate(object, groups); |
| | | if (!validate.isEmpty()) { |
| | | throw new ConstraintViolationException("åæ°æ ¡éªå¼å¸¸", validate); |
| | | } |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils.file; |
| | | |
| | | import cn.hutool.core.io.FileUtil; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.net.URLEncoder; |
| | | import java.nio.charset.StandardCharsets; |
| | | |
| | | /** |
| | | * æä»¶å¤çå·¥å
·ç±» |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE) |
| | | public class FileUtils extends FileUtil { |
| | | |
| | | /** |
| | | * ä¸è½½æä»¶åéæ°ç¼ç |
| | | * |
| | | * @param response ååºå¯¹è±¡ |
| | | * @param realFileName ç宿件å |
| | | */ |
| | | public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) { |
| | | String percentEncodedFileName = percentEncode(realFileName); |
| | | String contentDispositionValue = "attachment; filename=%s;filename*=utf-8''%s".formatted(percentEncodedFileName, percentEncodedFileName); |
| | | response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename"); |
| | | response.setHeader("Content-disposition", contentDispositionValue); |
| | | response.setHeader("download-filename", percentEncodedFileName); |
| | | } |
| | | |
| | | /** |
| | | * ç¾åå·ç¼ç å·¥å
·æ¹æ³ |
| | | * |
| | | * @param s éè¦ç¾åå·ç¼ç çå符串 |
| | | * @return ç¾åå·ç¼ç åçå符串 |
| | | */ |
| | | public static String percentEncode(String s) { |
| | | String encode = URLEncoder.encode(s, StandardCharsets.UTF_8); |
| | | return encode.replaceAll("\\+", "%20"); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils.file; |
| | | |
| | | /** |
| | | * åªä½ç±»åå·¥å
·ç±» |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | public class MimeTypeUtils { |
| | | public static final String IMAGE_PNG = "image/png"; |
| | | |
| | | public static final String IMAGE_JPG = "image/jpg"; |
| | | |
| | | public static final String IMAGE_JPEG = "image/jpeg"; |
| | | |
| | | public static final String IMAGE_BMP = "image/bmp"; |
| | | |
| | | public static final String IMAGE_GIF = "image/gif"; |
| | | |
| | | public static final String[] IMAGE_EXTENSION = {"bmp", "gif", "jpg", "jpeg", "png"}; |
| | | |
| | | public static final String[] FLASH_EXTENSION = {"swf", "flv"}; |
| | | |
| | | public static final String[] MEDIA_EXTENSION = {"swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg", |
| | | "asf", "rm", "rmvb"}; |
| | | |
| | | public static final String[] VIDEO_EXTENSION = {"mp4", "avi", "rmvb"}; |
| | | |
| | | public static final String[] DEFAULT_ALLOWED_EXTENSION = { |
| | | // å¾ç |
| | | "bmp", "gif", "jpg", "jpeg", "png", |
| | | // word excel powerpoint |
| | | "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt", |
| | | // å缩æä»¶ |
| | | "rar", "zip", "gz", "bz2", |
| | | // è§é¢æ ¼å¼ |
| | | "mp4", "avi", "rmvb", |
| | | // pdf |
| | | "pdf"}; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils.ip; |
| | | |
| | | import cn.hutool.http.HtmlUtil; |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.core.utils.NetUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | |
| | | /** |
| | | * è·åå°åç±» |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Slf4j |
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE) |
| | | public class AddressUtils { |
| | | |
| | | // æªç¥IP |
| | | public static final String UNKNOWN_IP = "XX XX"; |
| | | // å
ç½å°å |
| | | public static final String LOCAL_ADDRESS = "å
ç½IP"; |
| | | |
| | | public static String getRealAddressByIP(String ip) { |
| | | // å¤çç©ºä¸²å¹¶è¿æ»¤HTMLæ ç¾ |
| | | ip = HtmlUtil.cleanHtmlTag(StringUtils.blankToDefault(ip,"")); |
| | | // 夿æ¯å¦ä¸ºIPv4 |
| | | boolean isIPv4 = NetUtils.isIPv4(ip); |
| | | // 夿æ¯å¦ä¸ºIPv6 |
| | | boolean isIPv6 = NetUtils.isIPv6(ip); |
| | | // 妿䏿¯IPv4æIPv6ï¼åè¿åæªç¥IP |
| | | if (!isIPv4 && !isIPv6) { |
| | | return UNKNOWN_IP; |
| | | } |
| | | // å
ç½ä¸æ¥è¯¢ |
| | | if ((isIPv4 && NetUtils.isInnerIP(ip)) || (isIPv6 && NetUtils.isInnerIPv6(ip))) { |
| | | return LOCAL_ADDRESS; |
| | | } |
| | | // Tipsï¼Ip2Region æä¾äºç²¾ç®çIPv6å°ååºï¼ç²¾ç®çIPv6å°ååºå¹¶ä¸è½å®å
¨æ¯æIPv6å°åçæ¥è¯¢ï¼ä¸å确度ä¸å¯è½ä¼åå¨é®é¢ï¼å¦éè¦åç¡®çIPv6å°åæ¥è¯¢ï¼å»ºè®®èªè¡å®ç° |
| | | return RegionUtils.getRegion(ip); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils.ip; |
| | | |
| | | import cn.hutool.core.io.resource.ResourceUtil; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.lionsoul.ip2region.service.Config; |
| | | import org.lionsoul.ip2region.service.Ip2Region; |
| | | import org.lionsoul.ip2region.xdb.Util; |
| | | |
| | | import java.io.InputStream; |
| | | import java.time.Duration; |
| | | |
| | | /** |
| | | * IPå°åè¡æ¿åºåå·¥å
·ç±» |
| | | * åèå°åï¼<a href="https://gitee.com/lionsoul/ip2region/tree/master/binding/java">ip2region xdb java æ¥è¯¢å®¢æ·ç«¯å®ç°</a> |
| | | * xdbæ°æ®åºæä»¶ä¸è½½ï¼<a href="https://gitee.com/lionsoul/ip2region/tree/master/data">ip2region data</a> |
| | | * |
| | | * @author ç§è¾æªå¯ |
| | | */ |
| | | @Slf4j |
| | | public class RegionUtils { |
| | | |
| | | // é»è®¤IPv4å°ååºæä»¶è·¯å¾ |
| | | // ä¸è½½å°åï¼https://gitee.com/lionsoul/ip2region/blob/master/data/ip2region_v4.xdb |
| | | public static final String DEFAULT_IPV4_XDB_PATH = "ip2region_v4.xdb"; |
| | | |
| | | // é»è®¤IPv6å°ååºæä»¶è·¯å¾ |
| | | // ä¸è½½å°åï¼https://gitee.com/lionsoul/ip2region/blob/master/data/ip2region_v6.xdb |
| | | public static final String DEFAULT_IPV6_XDB_PATH = "ip2region_v6.xdb"; |
| | | |
| | | // é»è®¤ç¼ååç大å°ä¸º15MBï¼ä»
é对BufferCacheå
¨éè¯»åææï¼å¦æä½ çxdbæ°æ®åºå¾å¤§ï¼åç设置该å¼å¯ä»¥æææåBufferCache模å¼ä¸çæ¥è¯¢æçï¼å
·ä½å¯ä»¥æ¥çIp2RegionçREADMEï¼ |
| | | // 注æï¼è®¾ç½®è¿å¤§çå¼å¯è½ä¼ç³è¯·å
åæ¶ï¼å å
åä¸è¶³è导è´OOMï¼è¯·åç设置该å¼ã |
| | | // READMEï¼https://gitee.com/lionsoul/ip2region/tree/master/binding/java |
| | | public static final int DEFAULT_CACHE_SLICE_BYTES = 1024 * 1024 * 15; |
| | | |
| | | // æªç¥å°å |
| | | public static final String UNKNOWN_ADDRESS = "æªç¥"; |
| | | |
| | | // Ip2Regionæå¡å®ä¾ |
| | | private static Ip2Region ip2Region; |
| | | |
| | | // åå§åIp2Regionæå¡å®ä¾ |
| | | static { |
| | | try { |
| | | // 注æï¼Ip2Region çxdbæä»¶å è½½çç¥ CachePolicy æä¸ç§ï¼å嫿¯ï¼BufferCacheï¼å
¨é读åxdbå°å
åä¸ï¼ãVIndexCacheï¼é»è®¤çç¥ï¼æé读åå¹¶ç¼åï¼ãNoCacheï¼å®æ¶è¯»åï¼ |
| | | // æ¬é¡¹ç®å·¥å
·ä½¿ç¨ç CachePolicy 为 BufferCacheï¼BufferCacheä¼å è½½æ´ä¸ªxdbæä»¶å°å
åä¸ï¼setXdbInputStream ä»
æ¯æ BufferCache çç¥ã |
| | | // å 为å è½½æ´ä¸ªxdbæä»¶ä¼èè´¹é常大çå
åï¼å¦æä½ ä¸å¸æå è½½æ´ä¸ªxdbå°å
åä¸ï¼æ´æ¨èä½¿ç¨ VIndexCache æ NoCacheï¼å³å®æ¶è¯»åæä»¶ï¼çç¥å setXdbPath/setXdbFile å è½½æ¹æ³ï¼éè¦æ³¨æçä¸ç¹ï¼setXdbPath å setXdbFile 䏿¯æè¯»åClassPathï¼å³æºç åresourceç®å½ï¼ä¸çæä»¶ï¼ã |
| | | // ä¸è¬èè¨ï¼æ´å»ºè®®æxdbæ°æ®åºæ¾å°ä¸ä¸ªæå®çæä»¶ç®å½ä¸ï¼å³ä¸æå
è¿jarå
ä¸ï¼ï¼ç¶åä½¿ç¨ VIndexCache + é
åSearcherPoolçå¹¶åæ± è¯»åæ°æ®ï¼æ´æ¹ä¾¿éæ¶æ´æ°xdbæ°æ®åº |
| | | |
| | | InputStream v4InputStream = ResourceUtil.getStream(DEFAULT_IPV4_XDB_PATH); |
| | | |
| | | // IPv4é
ç½® |
| | | Config v4Config = Config.custom() |
| | | .setCachePolicy(Config.BufferCache) |
| | | //.setXdbFile(v4TempXdb) |
| | | .setXdbInputStream(v4InputStream) |
| | | // |
| | | .setCacheSliceBytes(DEFAULT_CACHE_SLICE_BYTES) |
| | | .asV4(); |
| | | |
| | | // IPv6é
ç½® |
| | | Config v6Config = null; |
| | | InputStream v6XdbInputStream = ResourceUtil.getStreamSafe(DEFAULT_IPV6_XDB_PATH); |
| | | if (v6XdbInputStream == null) { |
| | | log.warn("æªå è½½ IPv6 å°ååºï¼æªå¨ç±»è·¯å¾ä¸æ¾å°æä»¶ {}ãå½åä»
å¯ç¨ IPv4 æ¥è¯¢ãå¦éå¯ç¨ IPv6ï¼è¯·å° ip2region_v6.xdb æ¾ç½®å° resources ç®å½", DEFAULT_IPV6_XDB_PATH); |
| | | } else { |
| | | v6Config = Config.custom() |
| | | .setCachePolicy(Config.BufferCache) |
| | | //.setXdbFile(v6TempXdb) |
| | | .setXdbInputStream(v6XdbInputStream) |
| | | .setCacheSliceBytes(DEFAULT_CACHE_SLICE_BYTES) |
| | | .asV6(); |
| | | } |
| | | |
| | | // åå§åIp2Regionå®ä¾ |
| | | RegionUtils.ip2Region = Ip2Region.create(v4Config, v6Config); |
| | | log.debug("IPå·¥å
·åå§åæåï¼å è½½IPå°ååºæ°æ®æåï¼"); |
| | | } catch (Exception e) { |
| | | throw new ServiceException("RegionUtilsåå§å失败ï¼åå ï¼{}", e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®IPå°å离线è·ååå¸ |
| | | * |
| | | * @param ipString ipå°åå符串 |
| | | */ |
| | | public static String getRegion(String ipString) { |
| | | try { |
| | | String region = ip2Region.search(ipString); |
| | | if (StringUtils.isBlank(region)) { |
| | | region = UNKNOWN_ADDRESS; |
| | | } |
| | | return region; |
| | | } catch (Exception e) { |
| | | log.error("IPå°å离线è·ååå¸å¼å¸¸ {}", ipString); |
| | | return UNKNOWN_ADDRESS; |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®IPå°å离线è·ååå¸ |
| | | * |
| | | * @param ipBytes ipå°ååèæ°ç» |
| | | */ |
| | | public static String getRegion(byte[] ipBytes) { |
| | | try { |
| | | String region = ip2Region.search(ipBytes); |
| | | if (StringUtils.isBlank(region)) { |
| | | region = UNKNOWN_ADDRESS; |
| | | } |
| | | return region; |
| | | } catch (Exception e) { |
| | | log.error("IPå°å离线è·ååå¸å¼å¸¸ {}", Util.ipToString(ipBytes)); |
| | | return UNKNOWN_ADDRESS; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å
³éIp2Regionæå¡ |
| | | */ |
| | | public static void close() { |
| | | if (ip2Region == null) { |
| | | return; |
| | | } |
| | | try { |
| | | ip2Region.close(10000); |
| | | } catch (Exception e) { |
| | | log.error("Ip2Regionæå¡å
³éå¼å¸¸", e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å
³éIp2Regionæå¡ |
| | | * |
| | | * @param timeout å
³éè¶
æ¶æ¶é´ |
| | | */ |
| | | public static void close(final Duration timeout) { |
| | | if (ip2Region == null) { |
| | | return; |
| | | } |
| | | if (timeout == null) { |
| | | close(); |
| | | return; |
| | | } |
| | | try { |
| | | ip2Region.close(timeout.toMillis()); |
| | | } catch (Exception e) { |
| | | log.error("Ip2Regionæå¡å
³éå¼å¸¸", e); |
| | | } |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils.reflect; |
| | | |
| | | import cn.hutool.core.util.ReflectUtil; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.lang.reflect.Method; |
| | | |
| | | /** |
| | | * åå°å·¥å
·ç±». æä¾è°ç¨getter/setteræ¹æ³, 访é®ç§æåé, è°ç¨ç§ææ¹æ³, è·åæ³åç±»åClass, 被AOPè¿ççå®ç±»çå·¥å
·å½æ°. |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @SuppressWarnings("rawtypes") |
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE) |
| | | public class ReflectUtils extends ReflectUtil { |
| | | |
| | | private static final String SETTER_PREFIX = "set"; |
| | | |
| | | private static final String GETTER_PREFIX = "get"; |
| | | |
| | | /** |
| | | * è°ç¨Getteræ¹æ³. |
| | | * æ¯æå¤çº§ï¼å¦ï¼å¯¹è±¡å.对象å.æ¹æ³ |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public static <E> E invokeGetter(Object obj, String propertyName) { |
| | | Object object = obj; |
| | | for (String name : StringUtils.split(propertyName, ".")) { |
| | | String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name); |
| | | object = invoke(object, getterMethodName); |
| | | } |
| | | return (E) object; |
| | | } |
| | | |
| | | /** |
| | | * è°ç¨Setteræ¹æ³, ä»
å¹é
æ¹æ³åã |
| | | * æ¯æå¤çº§ï¼å¦ï¼å¯¹è±¡å.对象å.æ¹æ³ |
| | | */ |
| | | public static <E> void invokeSetter(Object obj, String propertyName, E value) { |
| | | Object object = obj; |
| | | String[] names = StringUtils.split(propertyName, "."); |
| | | for (int i = 0; i < names.length; i++) { |
| | | if (i < names.length - 1) { |
| | | String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]); |
| | | object = invoke(object, getterMethodName); |
| | | } else { |
| | | String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]); |
| | | Method method = getMethodByName(object.getClass(), setterMethodName); |
| | | invoke(object, method, value); |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils.regex; |
| | | |
| | | |
| | | import cn.hutool.core.util.ReUtil; |
| | | import org.dromara.common.core.constant.RegexConstants; |
| | | |
| | | /** |
| | | * æ£åç¸å
³å·¥å
·ç±» |
| | | * |
| | | * @author Feng |
| | | */ |
| | | public final class RegexUtils extends ReUtil { |
| | | |
| | | /** |
| | | * ä»è¾å
¥åç¬¦ä¸²ä¸æåå¹é
çé¨åï¼å¦ææ²¡æå¹é
åè¿åé»è®¤å¼ |
| | | * |
| | | * @param input è¦æåçè¾å
¥å符串 |
| | | * @param regex ç¨äºå¹é
çæ£å表达å¼ï¼å¯ä»¥ä½¿ç¨ {@link RegexConstants} ä¸å®ä¹ç常é |
| | | * @param defaultInput å¦ææ²¡æå¹é
æ¶è¿åçé»è®¤å¼ |
| | | * @return 妿æ¾å°å¹é
çé¨åï¼åè¿åå¹é
çé¨åï¼å¦åè¿åé»è®¤å¼ |
| | | */ |
| | | public static String extractFromString(String input, String regex, String defaultInput) { |
| | | try { |
| | | String str = ReUtil.get(regex, input, 1); |
| | | return str == null ? defaultInput : str; |
| | | } catch (Exception e) { |
| | | return defaultInput; |
| | | } |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils.regex; |
| | | |
| | | import cn.hutool.core.exceptions.ValidateException; |
| | | import cn.hutool.core.lang.Validator; |
| | | import org.dromara.common.core.factory.RegexPatternPoolFactory; |
| | | |
| | | import java.util.regex.Pattern; |
| | | |
| | | /** |
| | | * æ£ååæ®µæ ¡éªå¨ |
| | | * 主è¦éªè¯å段éç©ºãæ¯å¦ä¸ºæ»¡è¶³æå®æ ¼å¼ç |
| | | * |
| | | * @author Feng |
| | | */ |
| | | public class RegexValidator extends Validator { |
| | | |
| | | /** |
| | | * åå
¸ç±»åå¿
须以忝å¼å¤´ï¼ä¸åªè½ä¸ºï¼å°ååæ¯ï¼æ°åï¼ä¸æ»çº¿ï¼ |
| | | */ |
| | | public static final Pattern DICTIONARY_TYPE = RegexPatternPoolFactory.DICTIONARY_TYPE; |
| | | |
| | | /** |
| | | * 身份è¯å·ç ï¼å6ä½ï¼ |
| | | */ |
| | | public static final Pattern ID_CARD_LAST_6 = RegexPatternPoolFactory.ID_CARD_LAST_6; |
| | | |
| | | /** |
| | | * QQå·ç |
| | | */ |
| | | public static final Pattern QQ_NUMBER = RegexPatternPoolFactory.QQ_NUMBER; |
| | | |
| | | /** |
| | | * 鮿¿ç¼ç |
| | | */ |
| | | public static final Pattern POSTAL_CODE = RegexPatternPoolFactory.POSTAL_CODE; |
| | | |
| | | /** |
| | | * 注åè´¦å· |
| | | */ |
| | | public static final Pattern ACCOUNT = RegexPatternPoolFactory.ACCOUNT; |
| | | |
| | | /** |
| | | * å¯ç ï¼å
å«è³å°8个å符ï¼å
æ¬å¤§å忝ãå°ååæ¯ãæ°ååç¹æ®å符 |
| | | */ |
| | | public static final Pattern PASSWORD = RegexPatternPoolFactory.PASSWORD; |
| | | |
| | | /** |
| | | * éç¨ç¶æï¼0表示æ£å¸¸ï¼1表示åç¨ï¼ |
| | | */ |
| | | public static final Pattern STATUS = RegexPatternPoolFactory.STATUS; |
| | | |
| | | |
| | | /** |
| | | * æ£æ¥è¾å
¥çè´¦å·æ¯å¦å¹é
é¢å®ä¹çè§å |
| | | * |
| | | * @param value è¦éªè¯çè´¦å· |
| | | * @return å¦æè´¦å·ç¬¦åè§åï¼è¿å trueï¼å¦åï¼è¿å falseã |
| | | */ |
| | | public static boolean isAccount(CharSequence value) { |
| | | return isMatchRegex(ACCOUNT, value); |
| | | } |
| | | |
| | | /** |
| | | * éªè¯è¾å
¥çè´¦å·æ¯å¦ç¬¦åè§åï¼å¦æä¸ç¬¦åï¼åæåº ValidateException å¼å¸¸ |
| | | * |
| | | * @param value è¦éªè¯çè´¦å· |
| | | * @param errorMsg éªè¯å¤±è´¥æ¶æåºçå¼å¸¸æ¶æ¯ |
| | | * @param <T> CharSequence çåç±»å |
| | | * @return 妿éªè¯éè¿ï¼è¿åè¾å
¥çè´¦å· |
| | | * @throws ValidateException 妿éªè¯å¤±è´¥ |
| | | */ |
| | | public static <T extends CharSequence> T validateAccount(T value, String errorMsg) throws ValidateException { |
| | | if (!isAccount(value)) { |
| | | throw new ValidateException(errorMsg); |
| | | } |
| | | return value; |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥è¾å
¥çç¶ææ¯å¦å¹é
é¢å®ä¹çè§å |
| | | * |
| | | * @param value è¦éªè¯çç¶æ |
| | | * @return å¦æç¶æç¬¦åè§åï¼è¿å trueï¼å¦åï¼è¿å falseã |
| | | */ |
| | | public static boolean isStatus(CharSequence value) { |
| | | return isMatchRegex(STATUS, value); |
| | | } |
| | | |
| | | /** |
| | | * éªè¯è¾å
¥çç¶ææ¯å¦ç¬¦åè§åï¼å¦æä¸ç¬¦åï¼åæåº ValidateException å¼å¸¸ |
| | | * |
| | | * @param value è¦éªè¯çç¶æ |
| | | * @param errorMsg éªè¯å¤±è´¥æ¶æåºçå¼å¸¸æ¶æ¯ |
| | | * @param <T> CharSequence çåç±»å |
| | | * @return 妿éªè¯éè¿ï¼è¿åè¾å
¥çç¶æ |
| | | * @throws ValidateException 妿éªè¯å¤±è´¥ |
| | | */ |
| | | public static <T extends CharSequence> T validateStatus(T value, String errorMsg) throws ValidateException { |
| | | if (!isStatus(value)) { |
| | | throw new ValidateException(errorMsg); |
| | | } |
| | | return value; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.utils.sql; |
| | | |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | |
| | | /** |
| | | * sqlæä½å·¥å
·ç±» |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE) |
| | | public class SqlUtil { |
| | | |
| | | /** |
| | | * å®ä¹å¸¸ç¨ç sqlå
³é®å |
| | | */ |
| | | public static String SQL_REGEX = "\u000B|and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()"; |
| | | |
| | | /** |
| | | * ä»
æ¯æåæ¯ãæ°åãä¸å线ãç©ºæ ¼ãéå·ãå°æ°ç¹ï¼æ¯æå¤ä¸ªå段æåºï¼ |
| | | */ |
| | | public static final String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+"; |
| | | |
| | | /** |
| | | * æ£æ¥å符ï¼é²æ¢æ³¨å
¥ç»è¿ |
| | | */ |
| | | public static String escapeOrderBySql(String value) { |
| | | if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) { |
| | | throw new IllegalArgumentException("åæ°ä¸ç¬¦åè§èï¼ä¸è½è¿è¡æ¥è¯¢"); |
| | | } |
| | | return value; |
| | | } |
| | | |
| | | /** |
| | | * éªè¯ order by è¯æ³æ¯å¦ç¬¦åè§è |
| | | */ |
| | | public static boolean isValidOrderBySql(String value) { |
| | | return value.matches(SQL_PATTERN); |
| | | } |
| | | |
| | | /** |
| | | * SQLå
³é®åæ£æ¥ |
| | | */ |
| | | public static void filterKeyword(String value) { |
| | | if (StringUtils.isEmpty(value)) { |
| | | return; |
| | | } |
| | | String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|"); |
| | | for (String sqlKeyword : sqlKeywords) { |
| | | if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1) { |
| | | throw new IllegalArgumentException("åæ°åå¨SQL注å
¥é£é©"); |
| | | } |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.validate; |
| | | |
| | | /** |
| | | * æ ¡éªåç» add |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public interface AddGroup { |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.validate; |
| | | |
| | | /** |
| | | * æ ¡éªåç» edit |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public interface EditGroup { |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.validate; |
| | | |
| | | /** |
| | | * æ ¡éªåç» query |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public interface QueryGroup { |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.validate.dicts; |
| | | |
| | | import jakarta.validation.Constraint; |
| | | import jakarta.validation.Payload; |
| | | |
| | | import java.lang.annotation.ElementType; |
| | | import java.lang.annotation.Retention; |
| | | import java.lang.annotation.RetentionPolicy; |
| | | import java.lang.annotation.Target; |
| | | |
| | | /** |
| | | * åå
¸é¡¹æ ¡éªæ³¨è§£ |
| | | * |
| | | * @author AprilWind |
| | | */ |
| | | @Constraint(validatedBy = DictPatternValidator.class) |
| | | @Target({ElementType.FIELD, ElementType.PARAMETER}) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | public @interface DictPattern { |
| | | |
| | | /** |
| | | * åå
¸ç±»åï¼å¦ "sys_user_sex" |
| | | */ |
| | | String dictType(); |
| | | |
| | | /** |
| | | * åé符 |
| | | */ |
| | | String separator(); |
| | | |
| | | /** |
| | | * é»è®¤æ ¡éªå¤±è´¥æç¤ºä¿¡æ¯ |
| | | */ |
| | | String message() default "åå
¸å¼æ æ"; |
| | | |
| | | Class<?>[] groups() default {}; |
| | | |
| | | Class<? extends Payload>[] payload() default {}; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.validate.dicts; |
| | | |
| | | import jakarta.validation.ConstraintValidator; |
| | | import jakarta.validation.ConstraintValidatorContext; |
| | | import org.dromara.common.core.service.DictService; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | |
| | | /** |
| | | * èªå®ä¹åå
¸å¼æ ¡éªå¨ |
| | | * |
| | | * @author AprilWind |
| | | */ |
| | | public class DictPatternValidator implements ConstraintValidator<DictPattern, String> { |
| | | |
| | | /** |
| | | * åå
¸ç±»å |
| | | */ |
| | | private String dictType; |
| | | |
| | | /** |
| | | * åé符 |
| | | */ |
| | | private String separator = ","; |
| | | |
| | | /** |
| | | * åå§åæ ¡éªå¨ï¼æå注解ä¸çåå
¸ç±»å |
| | | * |
| | | * @param annotation 注解å®ä¾ |
| | | */ |
| | | @Override |
| | | public void initialize(DictPattern annotation) { |
| | | this.dictType = annotation.dictType(); |
| | | if (StringUtils.isNotBlank(annotation.separator())) { |
| | | this.separator = annotation.separator(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªåæ®µå¼æ¯å¦ä¸ºæå®åå
¸ç±»åä¸çåæ³å¼ |
| | | * |
| | | * @param value è¢«æ ¡éªçåæ®µå¼ |
| | | * @param context æ ¡éªä¸ä¸æï¼å¯ç¨äºæå»ºé误信æ¯ï¼ |
| | | * @return true è¡¨ç¤ºæ ¡éªéè¿ï¼åæ³åå
¸å¼ï¼ï¼false 表示ä¸éè¿ |
| | | */ |
| | | @Override |
| | | public boolean isValid(String value, ConstraintValidatorContext context) { |
| | | if (StringUtils.isBlank(dictType) || StringUtils.isBlank(value)) { |
| | | return false; |
| | | } |
| | | String dictLabel = SpringUtils.getBean(DictService.class).getDictLabel(dictType, value, separator); |
| | | return StringUtils.isNotBlank(dictLabel); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.validate.enumd;
|
| | |
|
| | | import jakarta.validation.Constraint;
|
| | | import jakarta.validation.Payload;
|
| | |
|
| | | import java.lang.annotation.*;
|
| | |
|
| | | import static java.lang.annotation.ElementType.*;
|
| | | import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
| | |
|
| | | /**
|
| | | * èªå®ä¹æä¸¾æ ¡éª
|
| | | *
|
| | | * @author ç§è¾æªå¯
|
| | | * @date 2024-12-09
|
| | | */
|
| | | @Documented
|
| | | @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
|
| | | @Retention(RUNTIME)
|
| | | @Repeatable(EnumPattern.List.class) // å
许å¨åä¸å
ç´ ä¸å¤æ¬¡ä½¿ç¨è¯¥æ³¨è§£
|
| | | @Constraint(validatedBy = {EnumPatternValidator.class})
|
| | | public @interface EnumPattern {
|
| | |
|
| | | /**
|
| | | * éè¦æ ¡éªçæä¸¾ç±»å
|
| | | */
|
| | | Class<? extends Enum<?>> type();
|
| | |
|
| | | /**
|
| | | * æä¸¾ç±»åæ ¡éªå¼å段åç§°
|
| | | * éç¡®ä¿è¯¥å段å®ç°äº getter æ¹æ³
|
| | | */
|
| | | String fieldName();
|
| | |
|
| | | String message() default "è¾å
¥å¼ä¸å¨æä¸¾èå´å
";
|
| | |
|
| | | Class<?>[] groups() default {};
|
| | |
|
| | | Class<? extends Payload>[] payload() default {};
|
| | |
|
| | | @Documented
|
| | | @Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
|
| | | @Retention(RUNTIME)
|
| | | @interface List {
|
| | | EnumPattern[] value();
|
| | | }
|
| | |
|
| | | }
|
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.validate.enumd; |
| | | |
| | | import jakarta.validation.ConstraintValidator; |
| | | import jakarta.validation.ConstraintValidatorContext; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.core.utils.reflect.ReflectUtils; |
| | | |
| | | /** |
| | | * èªå®ä¹æä¸¾æ ¡éªæ³¨è§£å®ç° |
| | | * |
| | | * @author ç§è¾æªå¯ |
| | | * @date 2024-12-09 |
| | | */ |
| | | public class EnumPatternValidator implements ConstraintValidator<EnumPattern, String> { |
| | | |
| | | private EnumPattern annotation; |
| | | |
| | | @Override |
| | | public void initialize(EnumPattern annotation) { |
| | | ConstraintValidator.super.initialize(annotation); |
| | | this.annotation = annotation; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) { |
| | | if (StringUtils.isNotBlank(value)) { |
| | | String fieldName = annotation.fieldName(); |
| | | for (Object e : annotation.type().getEnumConstants()) { |
| | | if (value.equals(ReflectUtils.invokeGetter(e, fieldName))) { |
| | | return true; |
| | | } |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.xss; |
| | | |
| | | import jakarta.validation.Constraint; |
| | | import jakarta.validation.Payload; |
| | | import java.lang.annotation.ElementType; |
| | | import java.lang.annotation.Retention; |
| | | import java.lang.annotation.RetentionPolicy; |
| | | import java.lang.annotation.Target; |
| | | |
| | | /** |
| | | * èªå®ä¹xssæ ¡éªæ³¨è§£ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @Target(value = {ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER}) |
| | | @Constraint(validatedBy = {XssValidator.class}) |
| | | public @interface Xss { |
| | | |
| | | String message() default "ä¸å
许任ä½èæ¬è¿è¡"; |
| | | |
| | | Class<?>[] groups() default {}; |
| | | |
| | | Class<? extends Payload>[] payload() default {}; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.core.xss; |
| | | |
| | | import cn.hutool.core.util.ReUtil; |
| | | import cn.hutool.http.HtmlUtil; |
| | | |
| | | import jakarta.validation.ConstraintValidator; |
| | | import jakarta.validation.ConstraintValidatorContext; |
| | | |
| | | /** |
| | | * èªå®ä¹xssæ ¡éªæ³¨è§£å®ç° |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public class XssValidator implements ConstraintValidator<Xss, String> { |
| | | |
| | | @Override |
| | | public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) { |
| | | return !ReUtil.contains(HtmlUtil.RE_HTML_MARK, value); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | org.dromara.common.core.config.ApplicationConfig |
| | | org.dromara.common.core.config.ThreadPoolConfig |
| | | org.dromara.common.core.config.ValidatorConfig |
| | | org.dromara.common.core.utils.SpringUtils |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>5.5.3</version> |
| | | </parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-doc</artifactId> |
| | | <version>5.5.3</version> |
| | | <description>ruoyi-common-doc ç³»ç»æ¥å£</description> |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springdoc</groupId> |
| | | <artifactId>springdoc-openapi-starter-webmvc-api</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.github.therapi</groupId> |
| | | <artifactId>therapi-runtime-javadoc</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.fasterxml.jackson.module</groupId> |
| | | <artifactId>jackson-module-kotlin</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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"> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>${revision}</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>ruoyi-common-doc</artifactId> |
| | | |
| | | <description> |
| | | ruoyi-common-doc ç³»ç»æ¥å£ |
| | | </description> |
| | | |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.springdoc</groupId> |
| | | <artifactId>springdoc-openapi-starter-webmvc-api</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.github.therapi</groupId> |
| | | <artifactId>therapi-runtime-javadoc</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.fasterxml.jackson.module</groupId> |
| | | <artifactId>jackson-module-kotlin</artifactId> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.doc.config; |
| | | |
| | | import io.swagger.v3.oas.models.OpenAPI; |
| | | import io.swagger.v3.oas.models.Paths; |
| | | import io.swagger.v3.oas.models.info.Info; |
| | | import io.swagger.v3.oas.models.security.SecurityRequirement; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.doc.config.properties.SpringDocProperties; |
| | | import org.dromara.common.doc.handler.OpenApiHandler; |
| | | import org.springdoc.core.configuration.SpringDocConfiguration; |
| | | import org.springdoc.core.customizers.OpenApiBuilderCustomizer; |
| | | import org.springdoc.core.customizers.OpenApiCustomizer; |
| | | import org.springdoc.core.customizers.ServerBaseUrlCustomizer; |
| | | import org.springdoc.core.properties.SpringDocConfigProperties; |
| | | import org.springdoc.core.providers.JavadocProvider; |
| | | import org.springdoc.core.service.OpenAPIService; |
| | | import org.springdoc.core.service.SecurityService; |
| | | import org.springdoc.core.utils.PropertyResolverUtils; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.boot.autoconfigure.web.ServerProperties; |
| | | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| | | import org.springframework.context.annotation.Bean; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Optional; |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * æ¥å£ææ¡£é
ç½® |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @AutoConfiguration(before = SpringDocConfiguration.class) |
| | | @EnableConfigurationProperties(SpringDocProperties.class) |
| | | @ConditionalOnProperty(name = "springdoc.api-docs.enabled", havingValue = "true", matchIfMissing = true) |
| | | public class SpringDocConfig { |
| | | |
| | | private final ServerProperties serverProperties; |
| | | |
| | | @Bean |
| | | @ConditionalOnMissingBean(OpenAPI.class) |
| | | public OpenAPI openApi(SpringDocProperties properties) { |
| | | OpenAPI openApi = new OpenAPI(); |
| | | // ææ¡£åºæ¬ä¿¡æ¯ |
| | | SpringDocProperties.InfoProperties infoProperties = properties.getInfo(); |
| | | Info info = convertInfo(infoProperties); |
| | | openApi.info(info); |
| | | // æ©å±ææ¡£ä¿¡æ¯ |
| | | openApi.externalDocs(properties.getExternalDocs()); |
| | | openApi.tags(properties.getTags()); |
| | | openApi.paths(properties.getPaths()); |
| | | if (properties.getComponents() != null) { |
| | | openApi.components(properties.getComponents()); |
| | | Set<String> keySet = properties.getComponents().getSecuritySchemes().keySet(); |
| | | List<SecurityRequirement> list = new ArrayList<>(); |
| | | SecurityRequirement securityRequirement = new SecurityRequirement(); |
| | | keySet.forEach(securityRequirement::addList); |
| | | list.add(securityRequirement); |
| | | openApi.security(list); |
| | | } |
| | | return openApi; |
| | | } |
| | | |
| | | private Info convertInfo(SpringDocProperties.InfoProperties infoProperties) { |
| | | Info info = new Info(); |
| | | info.setTitle(infoProperties.getTitle()); |
| | | info.setDescription(infoProperties.getDescription()); |
| | | info.setContact(infoProperties.getContact()); |
| | | info.setLicense(infoProperties.getLicense()); |
| | | info.setVersion(infoProperties.getVersion()); |
| | | return info; |
| | | } |
| | | |
| | | /** |
| | | * èªå®ä¹ openapi å¤çå¨ |
| | | */ |
| | | @Bean |
| | | public OpenAPIService openApiBuilder(Optional<OpenAPI> openAPI, |
| | | SecurityService securityParser, |
| | | SpringDocConfigProperties springDocConfigProperties, PropertyResolverUtils propertyResolverUtils, |
| | | Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomisers, |
| | | Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomisers, Optional<JavadocProvider> javadocProvider) { |
| | | return new OpenApiHandler(openAPI, securityParser, springDocConfigProperties, propertyResolverUtils, openApiBuilderCustomisers, serverBaseUrlCustomisers, javadocProvider); |
| | | } |
| | | |
| | | /** |
| | | * 对已ç»çæå¥½ç OpenApi è¿è¡èªå®ä¹æä½ |
| | | */ |
| | | @Bean |
| | | public OpenApiCustomizer openApiCustomizer() { |
| | | String contextPath = serverProperties.getServlet().getContextPath(); |
| | | String finalContextPath; |
| | | if (StringUtils.isBlank(contextPath) || "/".equals(contextPath)) { |
| | | finalContextPath = ""; |
| | | } else { |
| | | finalContextPath = contextPath; |
| | | } |
| | | // 对ææè·¯å¾å¢å åç½®ä¸ä¸æè·¯å¾ |
| | | return openApi -> { |
| | | Paths oldPaths = openApi.getPaths(); |
| | | if (oldPaths instanceof PlusPaths) { |
| | | return; |
| | | } |
| | | PlusPaths newPaths = new PlusPaths(); |
| | | oldPaths.forEach((k, v) -> newPaths.addPathItem(finalContextPath + k, v)); |
| | | openApi.setPaths(newPaths); |
| | | }; |
| | | } |
| | | |
| | | /** |
| | | * åç¬ä½¿ç¨ä¸ä¸ªç±»ä¾¿äºå¤æ è§£å³springdocè·¯å¾æ¼æ¥éå¤é®é¢ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | static class PlusPaths extends Paths { |
| | | |
| | | public PlusPaths() { |
| | | super(); |
| | | } |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.doc.config.properties; |
| | | |
| | | import io.swagger.v3.oas.models.Components; |
| | | import io.swagger.v3.oas.models.ExternalDocumentation; |
| | | import io.swagger.v3.oas.models.Paths; |
| | | import io.swagger.v3.oas.models.info.Contact; |
| | | import io.swagger.v3.oas.models.info.License; |
| | | import io.swagger.v3.oas.models.tags.Tag; |
| | | import lombok.Data; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | import org.springframework.boot.context.properties.NestedConfigurationProperty; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * swagger é
ç½®å±æ§ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Data |
| | | @ConfigurationProperties(prefix = "springdoc") |
| | | public class SpringDocProperties { |
| | | |
| | | /** |
| | | * ææ¡£åºæ¬ä¿¡æ¯ |
| | | */ |
| | | @NestedConfigurationProperty |
| | | private InfoProperties info = new InfoProperties(); |
| | | |
| | | /** |
| | | * æ©å±ææ¡£å°å |
| | | */ |
| | | @NestedConfigurationProperty |
| | | private ExternalDocumentation externalDocs; |
| | | |
| | | /** |
| | | * æ ç¾ |
| | | */ |
| | | private List<Tag> tags = null; |
| | | |
| | | /** |
| | | * è·¯å¾ |
| | | */ |
| | | @NestedConfigurationProperty |
| | | private Paths paths = null; |
| | | |
| | | /** |
| | | * ç»ä»¶ |
| | | */ |
| | | @NestedConfigurationProperty |
| | | private Components components = null; |
| | | |
| | | /** |
| | | * <p> |
| | | * ææ¡£çåºç¡å±æ§ä¿¡æ¯ |
| | | * </p> |
| | | * |
| | | * @see io.swagger.v3.oas.models.info.Info |
| | | * |
| | | * ä¸ºäº springboot èªå¨ç产é
ç½®æç¤ºä¿¡æ¯ï¼æä»¥è¿éå¤å¶ä¸ä¸ªç±»åºæ¥ |
| | | */ |
| | | @Data |
| | | public static class InfoProperties { |
| | | |
| | | /** |
| | | * æ é¢ |
| | | */ |
| | | private String title = null; |
| | | |
| | | /** |
| | | * æè¿° |
| | | */ |
| | | private String description = null; |
| | | |
| | | /** |
| | | * èç³»äººä¿¡æ¯ |
| | | */ |
| | | @NestedConfigurationProperty |
| | | private Contact contact = null; |
| | | |
| | | /** |
| | | * 许å¯è¯ |
| | | */ |
| | | @NestedConfigurationProperty |
| | | private License license = null; |
| | | |
| | | /** |
| | | * çæ¬ |
| | | */ |
| | | private String version = null; |
| | | |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.doc.handler; |
| | | |
| | | import cn.hutool.core.io.IoUtil; |
| | | import io.swagger.v3.core.jackson.TypeNameResolver; |
| | | import io.swagger.v3.core.util.AnnotationsUtils; |
| | | import io.swagger.v3.oas.annotations.tags.Tags; |
| | | import io.swagger.v3.oas.models.Components; |
| | | import io.swagger.v3.oas.models.OpenAPI; |
| | | import io.swagger.v3.oas.models.Operation; |
| | | import io.swagger.v3.oas.models.Paths; |
| | | import io.swagger.v3.oas.models.tags.Tag; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.dromara.common.core.utils.StreamUtils; |
| | | import org.springdoc.core.customizers.OpenApiBuilderCustomizer; |
| | | import org.springdoc.core.customizers.ServerBaseUrlCustomizer; |
| | | import org.springdoc.core.properties.SpringDocConfigProperties; |
| | | import org.springdoc.core.providers.JavadocProvider; |
| | | import org.springdoc.core.service.OpenAPIService; |
| | | import org.springdoc.core.service.SecurityService; |
| | | import org.springdoc.core.utils.PropertyResolverUtils; |
| | | import org.springframework.context.ApplicationContext; |
| | | import org.springframework.core.annotation.AnnotatedElementUtils; |
| | | import org.springframework.util.CollectionUtils; |
| | | import org.springframework.web.method.HandlerMethod; |
| | | |
| | | import java.io.StringReader; |
| | | import java.lang.reflect.Method; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | import java.util.stream.Stream; |
| | | |
| | | /** |
| | | * èªå®ä¹ openapi å¤çå¨ |
| | | * 对æºç åè½è¿è¡ä¿®æ¹ å¢å¼ºä½¿ç¨ |
| | | */ |
| | | @Slf4j |
| | | @SuppressWarnings("all") |
| | | public class OpenApiHandler extends OpenAPIService { |
| | | |
| | | /** |
| | | * The Basic error controller. |
| | | */ |
| | | private static Class<?> basicErrorController; |
| | | |
| | | /** |
| | | * The Security parser. |
| | | */ |
| | | private final SecurityService securityParser; |
| | | |
| | | /** |
| | | * The Mappings map. |
| | | */ |
| | | private final Map<String, Object> mappingsMap = new HashMap<>(); |
| | | |
| | | /** |
| | | * The Springdoc tags. |
| | | */ |
| | | private final Map<HandlerMethod, Tag> springdocTags = new HashMap<>(); |
| | | |
| | | /** |
| | | * The Open api builder customisers. |
| | | */ |
| | | private final Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomisers; |
| | | |
| | | /** |
| | | * The server base URL customisers. |
| | | */ |
| | | private final Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomizers; |
| | | |
| | | /** |
| | | * The Spring doc config properties. |
| | | */ |
| | | private final SpringDocConfigProperties springDocConfigProperties; |
| | | |
| | | /** |
| | | * The Cached open api map. |
| | | */ |
| | | private final Map<String, OpenAPI> cachedOpenAPI = new HashMap<>(); |
| | | |
| | | /** |
| | | * The Property resolver utils. |
| | | */ |
| | | private final PropertyResolverUtils propertyResolverUtils; |
| | | |
| | | /** |
| | | * The javadoc provider. |
| | | */ |
| | | private final Optional<JavadocProvider> javadocProvider; |
| | | |
| | | /** |
| | | * The Context. |
| | | */ |
| | | private ApplicationContext context; |
| | | |
| | | /** |
| | | * The Open api. |
| | | */ |
| | | private OpenAPI openAPI; |
| | | |
| | | /** |
| | | * The Is servers present. |
| | | */ |
| | | private boolean isServersPresent; |
| | | |
| | | /** |
| | | * The Server base url. |
| | | */ |
| | | private String serverBaseUrl; |
| | | |
| | | /** |
| | | * Instantiates a new Open api builder. |
| | | * |
| | | * @param openAPI the open api |
| | | * @param securityParser the security parser |
| | | * @param springDocConfigProperties the spring doc config properties |
| | | * @param propertyResolverUtils the property resolver utils |
| | | * @param openApiBuilderCustomizers the open api builder customisers |
| | | * @param serverBaseUrlCustomizers the server base url customizers |
| | | * @param javadocProvider the javadoc provider |
| | | */ |
| | | public OpenApiHandler(Optional<OpenAPI> openAPI, SecurityService securityParser, |
| | | SpringDocConfigProperties springDocConfigProperties, PropertyResolverUtils propertyResolverUtils, |
| | | Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomizers, |
| | | Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomizers, |
| | | Optional<JavadocProvider> javadocProvider) { |
| | | super(openAPI, securityParser, springDocConfigProperties, propertyResolverUtils, openApiBuilderCustomizers, serverBaseUrlCustomizers, javadocProvider); |
| | | if (openAPI.isPresent()) { |
| | | this.openAPI = openAPI.get(); |
| | | if (this.openAPI.getComponents() == null) |
| | | this.openAPI.setComponents(new Components()); |
| | | if (this.openAPI.getPaths() == null) |
| | | this.openAPI.setPaths(new Paths()); |
| | | if (!CollectionUtils.isEmpty(this.openAPI.getServers())) |
| | | this.isServersPresent = true; |
| | | } |
| | | this.propertyResolverUtils = propertyResolverUtils; |
| | | this.securityParser = securityParser; |
| | | this.springDocConfigProperties = springDocConfigProperties; |
| | | this.openApiBuilderCustomisers = openApiBuilderCustomizers; |
| | | this.serverBaseUrlCustomizers = serverBaseUrlCustomizers; |
| | | this.javadocProvider = javadocProvider; |
| | | if (springDocConfigProperties.isUseFqn()) |
| | | TypeNameResolver.std.setUseFqn(true); |
| | | } |
| | | |
| | | @Override |
| | | public Operation buildTags(HandlerMethod handlerMethod, Operation operation, OpenAPI openAPI, Locale locale) { |
| | | |
| | | Set<Tag> tags = new HashSet<>(); |
| | | Set<String> tagsStr = new HashSet<>(); |
| | | |
| | | buildTagsFromMethod(handlerMethod.getMethod(), tags, tagsStr, locale); |
| | | buildTagsFromClass(handlerMethod.getBeanType(), tags, tagsStr, locale); |
| | | |
| | | if (!CollectionUtils.isEmpty(tagsStr)) |
| | | tagsStr = tagsStr.stream() |
| | | .map(str -> propertyResolverUtils.resolve(str, locale)) |
| | | .collect(Collectors.toSet()); |
| | | |
| | | if (springdocTags.containsKey(handlerMethod)) { |
| | | io.swagger.v3.oas.models.tags.Tag tag = springdocTags.get(handlerMethod); |
| | | tagsStr.add(tag.getName()); |
| | | if (openAPI.getTags() == null || !openAPI.getTags().contains(tag)) { |
| | | openAPI.addTagsItem(tag); |
| | | } |
| | | } |
| | | |
| | | if (!CollectionUtils.isEmpty(tagsStr)) { |
| | | if (CollectionUtils.isEmpty(operation.getTags())) |
| | | operation.setTags(new ArrayList<>(tagsStr)); |
| | | else { |
| | | Set<String> operationTagsSet = new HashSet<>(operation.getTags()); |
| | | operationTagsSet.addAll(tagsStr); |
| | | operation.getTags().clear(); |
| | | operation.getTags().addAll(operationTagsSet); |
| | | } |
| | | } |
| | | |
| | | if (isAutoTagClasses(operation)) { |
| | | |
| | | |
| | | if (javadocProvider.isPresent()) { |
| | | String description = javadocProvider.get().getClassJavadoc(handlerMethod.getBeanType()); |
| | | if (StringUtils.isNotBlank(description)) { |
| | | io.swagger.v3.oas.models.tags.Tag tag = new io.swagger.v3.oas.models.tags.Tag(); |
| | | |
| | | // èªå®ä¹é¨å ä¿®æ¹ä½¿ç¨java注éå½tagå |
| | | List<String> list = IoUtil.readLines(new StringReader(description), new ArrayList<>()); |
| | | // tag.setName(tagAutoName); |
| | | tag.setName(list.get(0)); |
| | | operation.addTagsItem(list.get(0)); |
| | | |
| | | tag.setDescription(description); |
| | | if (openAPI.getTags() == null || !openAPI.getTags().contains(tag)) { |
| | | openAPI.addTagsItem(tag); |
| | | } |
| | | } |
| | | } else { |
| | | String tagAutoName = splitCamelCase(handlerMethod.getBeanType().getSimpleName()); |
| | | operation.addTagsItem(tagAutoName); |
| | | } |
| | | } |
| | | |
| | | if (!CollectionUtils.isEmpty(tags)) { |
| | | // Existing tags |
| | | List<io.swagger.v3.oas.models.tags.Tag> openApiTags = openAPI.getTags(); |
| | | if (!CollectionUtils.isEmpty(openApiTags)) |
| | | tags.addAll(openApiTags); |
| | | openAPI.setTags(new ArrayList<>(tags)); |
| | | } |
| | | |
| | | // Handle SecurityRequirement at operation level |
| | | io.swagger.v3.oas.annotations.security.SecurityRequirement[] securityRequirements = securityParser |
| | | .getSecurityRequirements(handlerMethod); |
| | | if (securityRequirements != null) { |
| | | if (securityRequirements.length == 0) |
| | | operation.setSecurity(Collections.emptyList()); |
| | | else |
| | | securityParser.buildSecurityRequirement(securityRequirements, operation); |
| | | } |
| | | |
| | | return operation; |
| | | } |
| | | |
| | | private void buildTagsFromMethod(Method method, Set<io.swagger.v3.oas.models.tags.Tag> tags, Set<String> tagsStr, Locale locale) { |
| | | // method tags |
| | | Set<Tags> tagsSet = AnnotatedElementUtils |
| | | .findAllMergedAnnotations(method, Tags.class); |
| | | Set<io.swagger.v3.oas.annotations.tags.Tag> methodTags = tagsSet.stream() |
| | | .flatMap(x -> Stream.of(x.value())).collect(Collectors.toSet()); |
| | | methodTags.addAll(AnnotatedElementUtils.findAllMergedAnnotations(method, io.swagger.v3.oas.annotations.tags.Tag.class)); |
| | | if (!CollectionUtils.isEmpty(methodTags)) { |
| | | tagsStr.addAll(StreamUtils.toSet(methodTags, tag -> propertyResolverUtils.resolve(tag.name(), locale))); |
| | | List<io.swagger.v3.oas.annotations.tags.Tag> allTags = new ArrayList<>(methodTags); |
| | | addTags(allTags, tags, locale); |
| | | } |
| | | } |
| | | |
| | | private void addTags(List<io.swagger.v3.oas.annotations.tags.Tag> sourceTags, Set<io.swagger.v3.oas.models.tags.Tag> tags, Locale locale) { |
| | | Optional<Set<io.swagger.v3.oas.models.tags.Tag>> optionalTagSet = AnnotationsUtils |
| | | .getTags(sourceTags.toArray(new io.swagger.v3.oas.annotations.tags.Tag[0]), true); |
| | | optionalTagSet.ifPresent(tagsSet -> { |
| | | tagsSet.forEach(tag -> { |
| | | tag.name(propertyResolverUtils.resolve(tag.getName(), locale)); |
| | | tag.description(propertyResolverUtils.resolve(tag.getDescription(), locale)); |
| | | if (tags.stream().noneMatch(t -> t.getName().equals(tag.getName()))) |
| | | tags.add(tag); |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | org.dromara.common.doc.config.SpringDocConfig |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>5.5.3</version> |
| | | </parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-encrypt</artifactId> |
| | | <version>5.5.3</version> |
| | | <description>ruoyi-common-encrypt æ°æ®å è§£å¯æ¨¡å</description> |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.bouncycastle</groupId> |
| | | <artifactId>bcprov-jdk15to18</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>cn.hutool</groupId> |
| | | <artifactId>hutool-crypto</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework</groupId> |
| | | <artifactId>spring-webmvc</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>mybatis-plus-spring-boot3-starter</artifactId> |
| | | <exclusions> |
| | | <exclusion> |
| | | <groupId>org.mybatis</groupId> |
| | | <artifactId>mybatis-spring</artifactId> |
| | | </exclusion> |
| | | </exclusions> |
| | | <optional>true</optional> |
| | | </dependency> |
| | | </dependencies> |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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"> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>${revision}</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>ruoyi-common-encrypt</artifactId> |
| | | |
| | | <description> |
| | | ruoyi-common-encrypt æ°æ®å è§£å¯æ¨¡å |
| | | </description> |
| | | |
| | | <dependencies> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.bouncycastle</groupId> |
| | | <artifactId>bcprov-jdk15to18</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>cn.hutool</groupId> |
| | | <artifactId>hutool-crypto</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.springframework</groupId> |
| | | <artifactId>spring-webmvc</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>mybatis-plus-spring-boot3-starter</artifactId> |
| | | <optional>true</optional> |
| | | <exclusions> |
| | | <exclusion> |
| | | <groupId>org.mybatis</groupId> |
| | | <artifactId>mybatis-spring</artifactId> |
| | | </exclusion> |
| | | </exclusions> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.annotation; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * 强å¶å 坿³¨è§£ |
| | | * |
| | | * @author Michelle.Chung |
| | | */ |
| | | @Documented |
| | | @Target({ElementType.METHOD}) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | public @interface ApiEncrypt { |
| | | |
| | | /** |
| | | * ååºå å¯å¿½ç¥ï¼é»è®¤ä¸å å¯ï¼ä¸º true æ¶å å¯ |
| | | */ |
| | | boolean response() default false; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.annotation; |
| | | |
| | | import org.dromara.common.encrypt.enumd.AlgorithmType; |
| | | import org.dromara.common.encrypt.enumd.EncodeType; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * åæ®µå 坿³¨è§£ |
| | | * |
| | | * @author è马 |
| | | */ |
| | | @Documented |
| | | @Inherited |
| | | @Target({ElementType.FIELD}) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | public @interface EncryptField { |
| | | |
| | | /** |
| | | * å å¯ç®æ³ |
| | | */ |
| | | AlgorithmType algorithm() default AlgorithmType.DEFAULT; |
| | | |
| | | /** |
| | | * ç§é¥ãAESãSM4éè¦ |
| | | */ |
| | | String password() default ""; |
| | | |
| | | /** |
| | | * å
¬é¥ãRSAãSM2éè¦ |
| | | */ |
| | | String publicKey() default ""; |
| | | |
| | | /** |
| | | * ç§é¥ãRSAãSM2éè¦ |
| | | */ |
| | | String privateKey() default ""; |
| | | |
| | | /** |
| | | * ç¼ç æ¹å¼ã对å å¯ç®æ³ä¸ºBASE64çä¸èµ·ä½ç¨ |
| | | */ |
| | | EncodeType encode() default EncodeType.DEFAULT; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.config; |
| | | |
| | | import jakarta.servlet.DispatcherType; |
| | | import org.dromara.common.encrypt.filter.CryptoFilter; |
| | | import org.dromara.common.encrypt.properties.ApiDecryptProperties; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| | | import org.springframework.boot.web.servlet.FilterRegistration; |
| | | import org.springframework.boot.web.servlet.FilterRegistrationBean; |
| | | import org.springframework.context.annotation.Bean; |
| | | |
| | | /** |
| | | * api è§£å¯èªå¨é
ç½® |
| | | * |
| | | * @author wdhcr |
| | | */ |
| | | @AutoConfiguration |
| | | @EnableConfigurationProperties(ApiDecryptProperties.class) |
| | | @ConditionalOnProperty(value = "api-decrypt.enabled", havingValue = "true") |
| | | public class ApiDecryptAutoConfiguration { |
| | | |
| | | @Bean |
| | | @FilterRegistration( |
| | | name = "cryptoFilter", |
| | | urlPatterns = "/*", |
| | | order = FilterRegistrationBean.HIGHEST_PRECEDENCE, |
| | | dispatcherTypes = DispatcherType.REQUEST |
| | | ) |
| | | public CryptoFilter cryptoFilter(ApiDecryptProperties properties) { |
| | | return new CryptoFilter(properties); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.config; |
| | | |
| | | import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; |
| | | import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.encrypt.core.EncryptorManager; |
| | | import org.dromara.common.encrypt.interceptor.MybatisDecryptInterceptor; |
| | | import org.dromara.common.encrypt.interceptor.MybatisEncryptInterceptor; |
| | | import org.dromara.common.encrypt.properties.EncryptorProperties; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| | | import org.springframework.context.annotation.Bean; |
| | | |
| | | /** |
| | | * å è§£å¯é
ç½® |
| | | * |
| | | * @author è马 |
| | | * @version 4.6.0 |
| | | */ |
| | | @AutoConfiguration(after = MybatisPlusAutoConfiguration.class) |
| | | @EnableConfigurationProperties(EncryptorProperties.class) |
| | | @ConditionalOnProperty(value = "mybatis-encryptor.enable", havingValue = "true") |
| | | @Slf4j |
| | | public class EncryptorAutoConfiguration { |
| | | |
| | | @Autowired |
| | | private EncryptorProperties properties; |
| | | |
| | | @Bean |
| | | public EncryptorManager encryptorManager(MybatisPlusProperties mybatisPlusProperties) { |
| | | return new EncryptorManager(mybatisPlusProperties.getTypeAliasesPackage()); |
| | | } |
| | | |
| | | @Bean |
| | | public MybatisEncryptInterceptor mybatisEncryptInterceptor(EncryptorManager encryptorManager) { |
| | | return new MybatisEncryptInterceptor(encryptorManager, properties); |
| | | } |
| | | |
| | | @Bean |
| | | public MybatisDecryptInterceptor mybatisDecryptInterceptor(EncryptorManager encryptorManager) { |
| | | return new MybatisDecryptInterceptor(encryptorManager, properties); |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.core; |
| | | |
| | | import org.dromara.common.encrypt.enumd.AlgorithmType; |
| | | import org.dromara.common.encrypt.enumd.EncodeType; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * å å¯ä¸ä¸æ ç¨äºencryptorä¼ éå¿
è¦çåæ°ã |
| | | * |
| | | * @author è马 |
| | | * @version 4.6.0 |
| | | */ |
| | | @Data |
| | | public class EncryptContext { |
| | | |
| | | /** |
| | | * é»è®¤ç®æ³ |
| | | */ |
| | | private AlgorithmType algorithm; |
| | | |
| | | /** |
| | | * å®å
¨ç§é¥ |
| | | */ |
| | | private String password; |
| | | |
| | | /** |
| | | * å
¬é¥ |
| | | */ |
| | | private String publicKey; |
| | | |
| | | /** |
| | | * ç§é¥ |
| | | */ |
| | | private String privateKey; |
| | | |
| | | /** |
| | | * ç¼ç æ¹å¼ï¼base64/hex |
| | | */ |
| | | private EncodeType encode; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.core; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ReflectUtil; |
| | | import lombok.NoArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.ibatis.io.Resources; |
| | | import org.dromara.common.core.constant.Constants; |
| | | import org.dromara.common.core.utils.ObjectUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.encrypt.annotation.EncryptField; |
| | | import org.springframework.context.ConfigurableApplicationContext; |
| | | import org.springframework.core.io.Resource; |
| | | import org.springframework.core.io.support.PathMatchingResourcePatternResolver; |
| | | import org.springframework.core.io.support.ResourcePatternResolver; |
| | | import org.springframework.core.type.ClassMetadata; |
| | | import org.springframework.core.type.classreading.CachingMetadataReaderFactory; |
| | | import org.springframework.util.ClassUtils; |
| | | |
| | | import java.lang.reflect.Field; |
| | | import java.util.Arrays; |
| | | import java.util.HashSet; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * å å¯ç®¡çç±» |
| | | * |
| | | * @author è马 |
| | | * @version 4.6.0 |
| | | */ |
| | | @Slf4j |
| | | @NoArgsConstructor |
| | | public class EncryptorManager { |
| | | |
| | | /** |
| | | * ç¼åå å¯å¨ |
| | | */ |
| | | Map<Integer, IEncryptor> encryptorMap = new ConcurrentHashMap<>(); |
| | | |
| | | /** |
| | | * ç±»å å¯å段ç¼å |
| | | */ |
| | | Map<Class<?>, Set<Field>> fieldCache = new ConcurrentHashMap<>(); |
| | | |
| | | /** |
| | | * æé æ¹æ³ä¼ å
¥ç±»å å¯å段ç¼å |
| | | * |
| | | * @param typeAliasesPackage å®ä½ç±»å
|
| | | */ |
| | | public EncryptorManager(String typeAliasesPackage) { |
| | | scanEncryptClasses(typeAliasesPackage); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * è·åç±»å å¯å段ç¼å |
| | | */ |
| | | public Set<Field> getFieldCache(Class<?> sourceClazz) { |
| | | return ObjectUtils.notNullGetter(fieldCache, f -> f.get(sourceClazz)); |
| | | } |
| | | |
| | | /** |
| | | * 注åå 坿§è¡è
å°ç¼å |
| | | * |
| | | * @param encryptContext å 坿§è¡è
éè¦çç¸å
³é
ç½®åæ° |
| | | */ |
| | | public IEncryptor registAndGetEncryptor(EncryptContext encryptContext) { |
| | | int key = encryptContext.hashCode(); |
| | | if (encryptorMap.containsKey(key)) { |
| | | return encryptorMap.get(key); |
| | | } |
| | | IEncryptor encryptor = ReflectUtil.newInstance(encryptContext.getAlgorithm().getClazz(), encryptContext); |
| | | encryptorMap.put(key, encryptor); |
| | | return encryptor; |
| | | } |
| | | |
| | | /** |
| | | * ç§»é¤ç¼åä¸çå 坿§è¡è
|
| | | * |
| | | * @param encryptContext å 坿§è¡è
éè¦çç¸å
³é
ç½®åæ° |
| | | */ |
| | | public void removeEncryptor(EncryptContext encryptContext) { |
| | | this.encryptorMap.remove(encryptContext.hashCode()); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®é
ç½®è¿è¡å å¯ãä¼è¿è¡æ¬å°ç¼å对åºçç®æ³å对åºçç§é¥ä¿¡æ¯ã |
| | | * |
| | | * @param value å¾
å å¯çå¼ |
| | | * @param encryptContext å å¯ç¸å
³çé
ç½®ä¿¡æ¯ |
| | | */ |
| | | public String encrypt(String value, EncryptContext encryptContext) { |
| | | if (StringUtils.startsWith(value, Constants.ENCRYPT_HEADER)) { |
| | | return value; |
| | | } |
| | | IEncryptor encryptor = this.registAndGetEncryptor(encryptContext); |
| | | String encrypt = encryptor.encrypt(value, encryptContext.getEncode()); |
| | | return Constants.ENCRYPT_HEADER + encrypt; |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®é
ç½®è¿è¡è§£å¯ |
| | | * |
| | | * @param value å¾
è§£å¯çå¼ |
| | | * @param encryptContext å å¯ç¸å
³çé
ç½®ä¿¡æ¯ |
| | | */ |
| | | public String decrypt(String value, EncryptContext encryptContext) { |
| | | if (!StringUtils.startsWith(value, Constants.ENCRYPT_HEADER)) { |
| | | return value; |
| | | } |
| | | IEncryptor encryptor = this.registAndGetEncryptor(encryptContext); |
| | | String str = StringUtils.removeStart(value, Constants.ENCRYPT_HEADER); |
| | | return encryptor.decrypt(str); |
| | | } |
| | | |
| | | /** |
| | | * éè¿ typeAliasesPackage è®¾ç½®çæ«æå
æ«æç¼åå®ä½ |
| | | */ |
| | | private void scanEncryptClasses(String typeAliasesPackage) { |
| | | PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); |
| | | CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory(); |
| | | String[] packagePatternArray = StringUtils.splitPreserveAllTokens(typeAliasesPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); |
| | | String classpath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX; |
| | | try { |
| | | for (String packagePattern : packagePatternArray) { |
| | | String path = ClassUtils.convertClassNameToResourcePath(packagePattern); |
| | | Resource[] resources = resolver.getResources(classpath + path + "/*.class"); |
| | | for (Resource resource : resources) { |
| | | ClassMetadata classMetadata = factory.getMetadataReader(resource).getClassMetadata(); |
| | | Class<?> clazz = Resources.classForName(classMetadata.getClassName()); |
| | | Set<Field> encryptFieldSet = getEncryptFieldSetFromClazz(clazz); |
| | | if (CollUtil.isNotEmpty(encryptFieldSet)) { |
| | | fieldCache.put(clazz, encryptFieldSet); |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("åå§åæ°æ®å®å
¨ç¼åæ¶åºé:{}", e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è·å¾ä¸ä¸ªç±»çå å¯å段éå |
| | | */ |
| | | private Set<Field> getEncryptFieldSetFromClazz(Class<?> clazz) { |
| | | Set<Field> fieldSet = new HashSet<>(); |
| | | // 夿clazzå¦ææ¯æ¥å£,å
é¨ç±»,å¿åç±»å°±ç´æ¥è¿å |
| | | if (clazz.isInterface() || clazz.isMemberClass() || clazz.isAnonymousClass()) { |
| | | return fieldSet; |
| | | } |
| | | while (clazz != null) { |
| | | Field[] fields = clazz.getDeclaredFields(); |
| | | fieldSet.addAll(Arrays.asList(fields)); |
| | | clazz = clazz.getSuperclass(); |
| | | } |
| | | fieldSet = fieldSet.stream().filter(field -> |
| | | field.isAnnotationPresent(EncryptField.class) && field.getType() == String.class) |
| | | .collect(Collectors.toSet()); |
| | | for (Field field : fieldSet) { |
| | | field.setAccessible(true); |
| | | } |
| | | return fieldSet; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.core; |
| | | |
| | | import org.dromara.common.encrypt.enumd.AlgorithmType; |
| | | import org.dromara.common.encrypt.enumd.EncodeType; |
| | | |
| | | /** |
| | | * å è§£è
|
| | | * |
| | | * @author è马 |
| | | * @version 4.6.0 |
| | | */ |
| | | public interface IEncryptor { |
| | | |
| | | /** |
| | | * è·å¾å½åç®æ³ |
| | | */ |
| | | AlgorithmType algorithm(); |
| | | |
| | | /** |
| | | * å å¯ |
| | | * |
| | | * @param value å¾
å å¯å符串 |
| | | * @param encodeType å å¯åçç¼ç æ ¼å¼ |
| | | * @return å å¯åçå符串 |
| | | */ |
| | | String encrypt(String value, EncodeType encodeType); |
| | | |
| | | /** |
| | | * è§£å¯ |
| | | * |
| | | * @param value å¾
å å¯å符串 |
| | | * @return è§£å¯åçå符串 |
| | | */ |
| | | String decrypt(String value); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.core.encryptor; |
| | | |
| | | import org.dromara.common.encrypt.core.EncryptContext; |
| | | import org.dromara.common.encrypt.core.IEncryptor; |
| | | |
| | | /** |
| | | * ææå 坿§è¡è
çåºç±» |
| | | * |
| | | * @author è马 |
| | | * @version 4.6.0 |
| | | */ |
| | | public abstract class AbstractEncryptor implements IEncryptor { |
| | | |
| | | public AbstractEncryptor(EncryptContext context) { |
| | | // ç¨æ·é
ç½®æ ¡éªä¸é
置注å
¥ |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.core.encryptor; |
| | | |
| | | import org.dromara.common.encrypt.core.EncryptContext; |
| | | import org.dromara.common.encrypt.enumd.AlgorithmType; |
| | | import org.dromara.common.encrypt.enumd.EncodeType; |
| | | import org.dromara.common.encrypt.utils.EncryptUtils; |
| | | |
| | | /** |
| | | * AESç®æ³å®ç° |
| | | * |
| | | * @author è马 |
| | | * @version 4.6.0 |
| | | */ |
| | | public class AesEncryptor extends AbstractEncryptor { |
| | | |
| | | private final EncryptContext context; |
| | | |
| | | public AesEncryptor(EncryptContext context) { |
| | | super(context); |
| | | this.context = context; |
| | | } |
| | | |
| | | /** |
| | | * è·å¾å½åç®æ³ |
| | | */ |
| | | @Override |
| | | public AlgorithmType algorithm() { |
| | | return AlgorithmType.AES; |
| | | } |
| | | |
| | | /** |
| | | * å å¯ |
| | | * |
| | | * @param value å¾
å å¯å符串 |
| | | * @param encodeType å å¯åçç¼ç æ ¼å¼ |
| | | */ |
| | | @Override |
| | | public String encrypt(String value, EncodeType encodeType) { |
| | | if (encodeType == EncodeType.HEX) { |
| | | return EncryptUtils.encryptByAesHex(value, context.getPassword()); |
| | | } else { |
| | | return EncryptUtils.encryptByAes(value, context.getPassword()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è§£å¯ |
| | | * |
| | | * @param value å¾
å å¯å符串 |
| | | */ |
| | | @Override |
| | | public String decrypt(String value) { |
| | | return EncryptUtils.decryptByAes(value, context.getPassword()); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.core.encryptor; |
| | | |
| | | import org.dromara.common.encrypt.core.EncryptContext; |
| | | import org.dromara.common.encrypt.enumd.AlgorithmType; |
| | | import org.dromara.common.encrypt.enumd.EncodeType; |
| | | import org.dromara.common.encrypt.utils.EncryptUtils; |
| | | |
| | | /** |
| | | * Base64ç®æ³å®ç° |
| | | * |
| | | * @author è马 |
| | | * @version 4.6.0 |
| | | */ |
| | | public class Base64Encryptor extends AbstractEncryptor { |
| | | |
| | | public Base64Encryptor(EncryptContext context) { |
| | | super(context); |
| | | } |
| | | |
| | | /** |
| | | * è·å¾å½åç®æ³ |
| | | */ |
| | | @Override |
| | | public AlgorithmType algorithm() { |
| | | return AlgorithmType.BASE64; |
| | | } |
| | | |
| | | /** |
| | | * å å¯ |
| | | * |
| | | * @param value å¾
å å¯å符串 |
| | | * @param encodeType å å¯åçç¼ç æ ¼å¼ |
| | | */ |
| | | @Override |
| | | public String encrypt(String value, EncodeType encodeType) { |
| | | return EncryptUtils.encryptByBase64(value); |
| | | } |
| | | |
| | | /** |
| | | * è§£å¯ |
| | | * |
| | | * @param value å¾
å å¯å符串 |
| | | */ |
| | | @Override |
| | | public String decrypt(String value) { |
| | | return EncryptUtils.decryptByBase64(value); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.core.encryptor; |
| | | |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.encrypt.core.EncryptContext; |
| | | import org.dromara.common.encrypt.enumd.AlgorithmType; |
| | | import org.dromara.common.encrypt.enumd.EncodeType; |
| | | import org.dromara.common.encrypt.utils.EncryptUtils; |
| | | |
| | | |
| | | /** |
| | | * RSAç®æ³å®ç° |
| | | * |
| | | * @author è马 |
| | | * @version 4.6.0 |
| | | */ |
| | | public class RsaEncryptor extends AbstractEncryptor { |
| | | |
| | | private final EncryptContext context; |
| | | |
| | | public RsaEncryptor(EncryptContext context) { |
| | | super(context); |
| | | String privateKey = context.getPrivateKey(); |
| | | String publicKey = context.getPublicKey(); |
| | | if (StringUtils.isAnyEmpty(privateKey, publicKey)) { |
| | | throw new IllegalArgumentException("RSAå
¬ç§é¥åéè¦æä¾ï¼å
¬é¥å å¯ï¼ç§é¥è§£å¯ã"); |
| | | } |
| | | this.context = context; |
| | | } |
| | | |
| | | /** |
| | | * è·å¾å½åç®æ³ |
| | | */ |
| | | @Override |
| | | public AlgorithmType algorithm() { |
| | | return AlgorithmType.RSA; |
| | | } |
| | | |
| | | /** |
| | | * å å¯ |
| | | * |
| | | * @param value å¾
å å¯å符串 |
| | | * @param encodeType å å¯åçç¼ç æ ¼å¼ |
| | | */ |
| | | @Override |
| | | public String encrypt(String value, EncodeType encodeType) { |
| | | if (encodeType == EncodeType.HEX) { |
| | | return EncryptUtils.encryptByRsaHex(value, context.getPublicKey()); |
| | | } else { |
| | | return EncryptUtils.encryptByRsa(value, context.getPublicKey()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è§£å¯ |
| | | * |
| | | * @param value å¾
å å¯å符串 |
| | | */ |
| | | @Override |
| | | public String decrypt(String value) { |
| | | return EncryptUtils.decryptByRsa(value, context.getPrivateKey()); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.core.encryptor; |
| | | |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.encrypt.core.EncryptContext; |
| | | import org.dromara.common.encrypt.enumd.AlgorithmType; |
| | | import org.dromara.common.encrypt.enumd.EncodeType; |
| | | import org.dromara.common.encrypt.utils.EncryptUtils; |
| | | |
| | | /** |
| | | * sm2ç®æ³å®ç° |
| | | * |
| | | * @author è马 |
| | | * @version 4.6.0 |
| | | */ |
| | | public class Sm2Encryptor extends AbstractEncryptor { |
| | | |
| | | private final EncryptContext context; |
| | | |
| | | public Sm2Encryptor(EncryptContext context) { |
| | | super(context); |
| | | String privateKey = context.getPrivateKey(); |
| | | String publicKey = context.getPublicKey(); |
| | | if (StringUtils.isAnyEmpty(privateKey, publicKey)) { |
| | | throw new IllegalArgumentException("SM2å
¬ç§é¥åéè¦æä¾ï¼å
¬é¥å å¯ï¼ç§é¥è§£å¯ã"); |
| | | } |
| | | this.context = context; |
| | | } |
| | | |
| | | /** |
| | | * è·å¾å½åç®æ³ |
| | | */ |
| | | @Override |
| | | public AlgorithmType algorithm() { |
| | | return AlgorithmType.SM2; |
| | | } |
| | | |
| | | /** |
| | | * å å¯ |
| | | * |
| | | * @param value å¾
å å¯å符串 |
| | | * @param encodeType å å¯åçç¼ç æ ¼å¼ |
| | | */ |
| | | @Override |
| | | public String encrypt(String value, EncodeType encodeType) { |
| | | if (encodeType == EncodeType.HEX) { |
| | | return EncryptUtils.encryptBySm2Hex(value, context.getPublicKey()); |
| | | } else { |
| | | return EncryptUtils.encryptBySm2(value, context.getPublicKey()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è§£å¯ |
| | | * |
| | | * @param value å¾
å å¯å符串 |
| | | */ |
| | | @Override |
| | | public String decrypt(String value) { |
| | | return EncryptUtils.decryptBySm2(value, context.getPrivateKey()); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.core.encryptor; |
| | | |
| | | import org.dromara.common.encrypt.core.EncryptContext; |
| | | import org.dromara.common.encrypt.enumd.AlgorithmType; |
| | | import org.dromara.common.encrypt.enumd.EncodeType; |
| | | import org.dromara.common.encrypt.utils.EncryptUtils; |
| | | |
| | | /** |
| | | * sm4ç®æ³å®ç° |
| | | * |
| | | * @author è马 |
| | | * @version 4.6.0 |
| | | */ |
| | | public class Sm4Encryptor extends AbstractEncryptor { |
| | | |
| | | private final EncryptContext context; |
| | | |
| | | public Sm4Encryptor(EncryptContext context) { |
| | | super(context); |
| | | this.context = context; |
| | | } |
| | | |
| | | /** |
| | | * è·å¾å½åç®æ³ |
| | | */ |
| | | @Override |
| | | public AlgorithmType algorithm() { |
| | | return AlgorithmType.SM4; |
| | | } |
| | | |
| | | /** |
| | | * å å¯ |
| | | * |
| | | * @param value å¾
å å¯å符串 |
| | | * @param encodeType å å¯åçç¼ç æ ¼å¼ |
| | | */ |
| | | @Override |
| | | public String encrypt(String value, EncodeType encodeType) { |
| | | if (encodeType == EncodeType.HEX) { |
| | | return EncryptUtils.encryptBySm4Hex(value, context.getPassword()); |
| | | } else { |
| | | return EncryptUtils.encryptBySm4(value, context.getPassword()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è§£å¯ |
| | | * |
| | | * @param value å¾
å å¯å符串 |
| | | */ |
| | | @Override |
| | | public String decrypt(String value) { |
| | | return EncryptUtils.decryptBySm4(value, context.getPassword()); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.enumd; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | import org.dromara.common.encrypt.core.encryptor.*; |
| | | |
| | | /** |
| | | * ç®æ³åç§° |
| | | * |
| | | * @author è马 |
| | | * @version 4.6.0 |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum AlgorithmType { |
| | | |
| | | /** |
| | | * é»è®¤èµ°ymlé
ç½® |
| | | */ |
| | | DEFAULT(null), |
| | | |
| | | /** |
| | | * base64 |
| | | */ |
| | | BASE64(Base64Encryptor.class), |
| | | |
| | | /** |
| | | * aes |
| | | */ |
| | | AES(AesEncryptor.class), |
| | | |
| | | /** |
| | | * rsa |
| | | */ |
| | | RSA(RsaEncryptor.class), |
| | | |
| | | /** |
| | | * sm2 |
| | | */ |
| | | SM2(Sm2Encryptor.class), |
| | | |
| | | /** |
| | | * sm4 |
| | | */ |
| | | SM4(Sm4Encryptor.class); |
| | | |
| | | private final Class<? extends AbstractEncryptor> clazz; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.enumd; |
| | | |
| | | /** |
| | | * ç¼ç ç±»å |
| | | * |
| | | * @author è马 |
| | | * @version 4.6.0 |
| | | */ |
| | | public enum EncodeType { |
| | | |
| | | /** |
| | | * é»è®¤ä½¿ç¨ymlé
ç½® |
| | | */ |
| | | DEFAULT, |
| | | |
| | | /** |
| | | * base64ç¼ç |
| | | */ |
| | | BASE64, |
| | | |
| | | /** |
| | | * 16è¿å¶ç¼ç |
| | | */ |
| | | HEX; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.filter; |
| | | |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import jakarta.servlet.*; |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import org.dromara.common.core.constant.HttpStatus; |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.encrypt.annotation.ApiEncrypt; |
| | | import org.dromara.common.encrypt.properties.ApiDecryptProperties; |
| | | import org.springframework.http.HttpMethod; |
| | | import org.springframework.web.method.HandlerMethod; |
| | | import org.springframework.web.servlet.HandlerExceptionResolver; |
| | | import org.springframework.web.servlet.HandlerExecutionChain; |
| | | import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; |
| | | |
| | | import java.io.IOException; |
| | | |
| | | |
| | | /** |
| | | * Crypto è¿æ»¤å¨ |
| | | * |
| | | * @author wdhcr |
| | | */ |
| | | public class CryptoFilter implements Filter { |
| | | private final ApiDecryptProperties properties; |
| | | |
| | | public CryptoFilter(ApiDecryptProperties properties) { |
| | | this.properties = properties; |
| | | } |
| | | |
| | | @Override |
| | | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { |
| | | HttpServletRequest servletRequest = (HttpServletRequest) request; |
| | | HttpServletResponse servletResponse = (HttpServletResponse) response; |
| | | // è·åå 坿³¨è§£ |
| | | ApiEncrypt apiEncrypt = this.getApiEncryptAnnotation(servletRequest); |
| | | boolean responseFlag = apiEncrypt != null && apiEncrypt.response(); |
| | | ServletRequest requestWrapper = null; |
| | | ServletResponse responseWrapper = null; |
| | | EncryptResponseBodyWrapper responseBodyWrapper = null; |
| | | |
| | | // æ¯å¦ä¸º put æè
post è¯·æ± |
| | | if (HttpMethod.PUT.matches(servletRequest.getMethod()) || HttpMethod.POST.matches(servletRequest.getMethod())) { |
| | | // æ¯å¦åå¨å 坿 头 |
| | | String headerValue = servletRequest.getHeader(properties.getHeaderFlag()); |
| | | if (StringUtils.isNotBlank(headerValue)) { |
| | | // 请æ±è§£å¯ |
| | | requestWrapper = new DecryptRequestBodyWrapper(servletRequest, properties.getPrivateKey(), properties.getHeaderFlag()); |
| | | } else { |
| | | // æ¯å¦ææ³¨è§£ï¼æå°±æ¥éï¼æ²¡ææ¾è¡ |
| | | if (ObjectUtil.isNotNull(apiEncrypt)) { |
| | | HandlerExceptionResolver exceptionResolver = SpringUtils.getBean("handlerExceptionResolver", HandlerExceptionResolver.class); |
| | | exceptionResolver.resolveException( |
| | | servletRequest, servletResponse, null, |
| | | new ServiceException("没æè®¿é®æéï¼è¯·è系管çåææ", HttpStatus.FORBIDDEN)); |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 夿æ¯å¦ååºå å¯ |
| | | if (responseFlag) { |
| | | responseBodyWrapper = new EncryptResponseBodyWrapper(servletResponse); |
| | | responseWrapper = responseBodyWrapper; |
| | | } |
| | | |
| | | chain.doFilter( |
| | | ObjectUtil.defaultIfNull(requestWrapper, request), |
| | | ObjectUtil.defaultIfNull(responseWrapper, response)); |
| | | |
| | | if (responseFlag) { |
| | | servletResponse.reset(); |
| | | // 对åå§å
容å å¯ |
| | | String encryptContent = responseBodyWrapper.getEncryptContent( |
| | | servletResponse, properties.getPublicKey(), properties.getHeaderFlag()); |
| | | // 对å å¯åçå
容ååº |
| | | servletResponse.getWriter().write(encryptContent); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è·å ApiEncrypt 注解 |
| | | */ |
| | | private ApiEncrypt getApiEncryptAnnotation(HttpServletRequest servletRequest) { |
| | | RequestMappingHandlerMapping handlerMapping = SpringUtils.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class); |
| | | // è·å注解 |
| | | try { |
| | | HandlerExecutionChain mappingHandler = handlerMapping.getHandler(servletRequest); |
| | | if (ObjectUtil.isNotNull(mappingHandler)) { |
| | | Object handler = mappingHandler.getHandler(); |
| | | if (ObjectUtil.isNotNull(handler)) { |
| | | // ä»handlerè·å注解 |
| | | if (handler instanceof HandlerMethod handlerMethod) { |
| | | return handlerMethod.getMethodAnnotation(ApiEncrypt.class); |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | return null; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public void destroy() { |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.filter; |
| | | |
| | | import cn.hutool.core.io.IoUtil; |
| | | import jakarta.servlet.ReadListener; |
| | | import jakarta.servlet.ServletInputStream; |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | import jakarta.servlet.http.HttpServletRequestWrapper; |
| | | import org.dromara.common.core.constant.Constants; |
| | | import org.dromara.common.encrypt.utils.EncryptUtils; |
| | | import org.springframework.http.MediaType; |
| | | |
| | | import java.io.BufferedReader; |
| | | import java.io.ByteArrayInputStream; |
| | | import java.io.IOException; |
| | | import java.io.InputStreamReader; |
| | | import java.nio.charset.StandardCharsets; |
| | | |
| | | /** |
| | | * è§£å¯è¯·æ±åæ°å·¥å
·ç±» |
| | | * |
| | | * @author wdhcr |
| | | */ |
| | | public class DecryptRequestBodyWrapper extends HttpServletRequestWrapper { |
| | | |
| | | private final byte[] body; |
| | | |
| | | public DecryptRequestBodyWrapper(HttpServletRequest request, String privateKey, String headerFlag) throws IOException { |
| | | super(request); |
| | | // è·å AES å¯ç éç¨ RSA å å¯ |
| | | String headerRsa = request.getHeader(headerFlag); |
| | | String decryptAes = EncryptUtils.decryptByRsa(headerRsa, privateKey); |
| | | // è§£å¯ AES å¯ç |
| | | String aesPassword = EncryptUtils.decryptByBase64(decryptAes); |
| | | request.setCharacterEncoding(Constants.UTF8); |
| | | byte[] readBytes = IoUtil.readBytes(request.getInputStream(), false); |
| | | String requestBody = new String(readBytes, StandardCharsets.UTF_8); |
| | | // è§£å¯ body éç¨ AES å å¯ |
| | | String decryptBody = EncryptUtils.decryptByAes(requestBody, aesPassword); |
| | | body = decryptBody.getBytes(StandardCharsets.UTF_8); |
| | | } |
| | | |
| | | @Override |
| | | public BufferedReader getReader() { |
| | | return new BufferedReader(new InputStreamReader(getInputStream())); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public int getContentLength() { |
| | | return body.length; |
| | | } |
| | | |
| | | @Override |
| | | public long getContentLengthLong() { |
| | | return body.length; |
| | | } |
| | | |
| | | @Override |
| | | public String getContentType() { |
| | | return MediaType.APPLICATION_JSON_VALUE; |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public ServletInputStream getInputStream() { |
| | | final ByteArrayInputStream bais = new ByteArrayInputStream(body); |
| | | return new ServletInputStream() { |
| | | @Override |
| | | public int read() { |
| | | return bais.read(); |
| | | } |
| | | |
| | | @Override |
| | | public int available() { |
| | | return body.length; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isFinished() { |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isReady() { |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public void setReadListener(ReadListener readListener) { |
| | | |
| | | } |
| | | }; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.filter; |
| | | |
| | | import cn.hutool.core.util.RandomUtil; |
| | | import jakarta.servlet.ServletOutputStream; |
| | | import jakarta.servlet.WriteListener; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import jakarta.servlet.http.HttpServletResponseWrapper; |
| | | import org.dromara.common.encrypt.utils.EncryptUtils; |
| | | |
| | | import java.io.*; |
| | | import java.nio.charset.StandardCharsets; |
| | | |
| | | /** |
| | | * å å¯ååºåæ°å
è£
ç±» |
| | | * |
| | | * @author Michelle.Chung |
| | | */ |
| | | public class EncryptResponseBodyWrapper extends HttpServletResponseWrapper { |
| | | |
| | | private final ByteArrayOutputStream byteArrayOutputStream; |
| | | private final ServletOutputStream servletOutputStream; |
| | | private final PrintWriter printWriter; |
| | | |
| | | public EncryptResponseBodyWrapper(HttpServletResponse response) throws IOException { |
| | | super(response); |
| | | this.byteArrayOutputStream = new ByteArrayOutputStream(); |
| | | this.servletOutputStream = this.getOutputStream(); |
| | | this.printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream)); |
| | | } |
| | | |
| | | @Override |
| | | public PrintWriter getWriter() { |
| | | return printWriter; |
| | | } |
| | | |
| | | @Override |
| | | public void flushBuffer() throws IOException { |
| | | if (servletOutputStream != null) { |
| | | servletOutputStream.flush(); |
| | | } |
| | | if (printWriter != null) { |
| | | printWriter.flush(); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void reset() { |
| | | byteArrayOutputStream.reset(); |
| | | } |
| | | |
| | | public byte[] getResponseData() throws IOException { |
| | | flushBuffer(); |
| | | return byteArrayOutputStream.toByteArray(); |
| | | } |
| | | |
| | | public String getContent() throws IOException { |
| | | flushBuffer(); |
| | | return byteArrayOutputStream.toString(); |
| | | } |
| | | |
| | | /** |
| | | * è·åå å¯å
容 |
| | | * |
| | | * @param servletResponse response |
| | | * @param publicKey RSAå
¬é¥ (ç¨äºå å¯ AES ç§é¥) |
| | | * @param headerFlag 请æ±å¤´æ å¿ |
| | | * @return å å¯å
容 |
| | | * @throws IOException |
| | | */ |
| | | public String getEncryptContent(HttpServletResponse servletResponse, String publicKey, String headerFlag) throws IOException { |
| | | // çæç§é¥ |
| | | String aesPassword = RandomUtil.randomString(32); |
| | | // ç§é¥ä½¿ç¨ Base64 ç¼ç |
| | | String encryptAes = EncryptUtils.encryptByBase64(aesPassword); |
| | | // Rsa å
¬é¥å å¯ Base64 ç¼ç |
| | | String encryptPassword = EncryptUtils.encryptByRsa(encryptAes, publicKey); |
| | | |
| | | // 设置ååºå¤´ |
| | | // vueçæ¬éè¦è®¾ç½® |
| | | servletResponse.addHeader("Access-Control-Expose-Headers", headerFlag); |
| | | servletResponse.setHeader("Access-Control-Allow-Origin", "*"); |
| | | servletResponse.setHeader("Access-Control-Allow-Methods", "*"); |
| | | servletResponse.setHeader(headerFlag, encryptPassword); |
| | | servletResponse.setCharacterEncoding(StandardCharsets.UTF_8.toString()); |
| | | |
| | | |
| | | // è·ååå§å
容 |
| | | String originalBody = this.getContent(); |
| | | // 对å
容è¿è¡å å¯ |
| | | return EncryptUtils.encryptByAes(originalBody, aesPassword); |
| | | } |
| | | |
| | | @Override |
| | | public ServletOutputStream getOutputStream() throws IOException { |
| | | return new ServletOutputStream() { |
| | | @Override |
| | | public boolean isReady() { |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public void setWriteListener(WriteListener writeListener) { |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public void write(int b) throws IOException { |
| | | byteArrayOutputStream.write(b); |
| | | } |
| | | |
| | | @Override |
| | | public void write(byte[] b) throws IOException { |
| | | byteArrayOutputStream.write(b); |
| | | } |
| | | |
| | | @Override |
| | | public void write(byte[] b, int off, int len) throws IOException { |
| | | byteArrayOutputStream.write(b, off, len); |
| | | } |
| | | }; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.interceptor; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.ibatis.executor.parameter.ParameterHandler; |
| | | import org.apache.ibatis.executor.resultset.ResultSetHandler; |
| | | import org.apache.ibatis.plugin.*; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.encrypt.annotation.EncryptField; |
| | | import org.dromara.common.encrypt.core.EncryptContext; |
| | | import org.dromara.common.encrypt.core.EncryptorManager; |
| | | import org.dromara.common.encrypt.enumd.AlgorithmType; |
| | | import org.dromara.common.encrypt.enumd.EncodeType; |
| | | import org.dromara.common.encrypt.properties.EncryptorProperties; |
| | | |
| | | import java.lang.reflect.Field; |
| | | import java.sql.Statement; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * åºåè§£å¯æ¦æªå¨ |
| | | * |
| | | * @author è马 |
| | | * @version 4.6.0 |
| | | */ |
| | | @Slf4j |
| | | @Intercepts({@Signature( |
| | | type = ResultSetHandler.class, |
| | | method = "handleResultSets", |
| | | args = {Statement.class}) |
| | | }) |
| | | @AllArgsConstructor |
| | | public class MybatisDecryptInterceptor implements Interceptor { |
| | | |
| | | private final EncryptorManager encryptorManager; |
| | | private final EncryptorProperties defaultProperties; |
| | | |
| | | @Override |
| | | public Object intercept(Invocation invocation) throws Throwable { |
| | | // å¼å§è¿è¡åæ°è§£å¯ |
| | | ResultSetHandler resultSetHandler = (ResultSetHandler) invocation.getTarget(); |
| | | Field parameterHandlerField = resultSetHandler.getClass().getDeclaredField("parameterHandler"); |
| | | parameterHandlerField.setAccessible(true); |
| | | Object target = parameterHandlerField.get(resultSetHandler); |
| | | if (target instanceof ParameterHandler parameterHandler) { |
| | | Object parameterObject = parameterHandler.getParameterObject(); |
| | | if (ObjectUtil.isNotNull(parameterObject) && !(parameterObject instanceof String)) { |
| | | this.decryptHandler(parameterObject); |
| | | } |
| | | } |
| | | // è·åæ§è¡mysqlæ§è¡ç»æ |
| | | Object result = invocation.proceed(); |
| | | if (result == null) { |
| | | return null; |
| | | } |
| | | this.decryptHandler(result); |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * è§£å¯å¯¹è±¡ |
| | | * |
| | | * @param sourceObject å¾
å å¯å¯¹è±¡ |
| | | */ |
| | | private void decryptHandler(Object sourceObject) { |
| | | if (ObjectUtil.isNull(sourceObject)) { |
| | | return; |
| | | } |
| | | if (sourceObject instanceof Map<?, ?> map) { |
| | | new HashSet<>(map.values()).forEach(this::decryptHandler); |
| | | return; |
| | | } |
| | | if (sourceObject instanceof List<?> list) { |
| | | if(CollUtil.isEmpty(list)) { |
| | | return; |
| | | } |
| | | // å¤æç¬¬ä¸ä¸ªå
ç´ æ¯å¦å«ææ³¨è§£ãå¦ææ²¡æç´æ¥è¿åï¼æé«æç |
| | | Object firstItem = list.get(0); |
| | | if (ObjectUtil.isNull(firstItem) || CollUtil.isEmpty(encryptorManager.getFieldCache(firstItem.getClass()))) { |
| | | return; |
| | | } |
| | | list.forEach(this::decryptHandler); |
| | | return; |
| | | } |
| | | // ä¸å¨ç¼åä¸çç±»,å°±æ¯æ²¡æå 坿³¨è§£çç±»(å½ç¶ä¹æå¯è½æ¯typeAliasesPackageåé) |
| | | Set<Field> fields = encryptorManager.getFieldCache(sourceObject.getClass()); |
| | | if(ObjectUtil.isNull(fields)){ |
| | | return; |
| | | } |
| | | try { |
| | | for (Field field : fields) { |
| | | field.set(sourceObject, this.decryptField(Convert.toStr(field.get(sourceObject)), field)); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("å¤çè§£å¯å段æ¶åºé", e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * åæ®µå¼è¿è¡å å¯ãéè¿åæ®µçæ¹æ³¨æ³¨åæ°çå å¯ç®æ³ |
| | | * |
| | | * @param value å¾
å å¯çå¼ |
| | | * @param field å¾
å å¯å段 |
| | | * @return å å¯åç»æ |
| | | */ |
| | | private String decryptField(String value, Field field) { |
| | | if (ObjectUtil.isNull(value)) { |
| | | return null; |
| | | } |
| | | EncryptField encryptField = field.getAnnotation(EncryptField.class); |
| | | EncryptContext encryptContext = new EncryptContext(); |
| | | encryptContext.setAlgorithm(encryptField.algorithm() == AlgorithmType.DEFAULT ? defaultProperties.getAlgorithm() : encryptField.algorithm()); |
| | | encryptContext.setEncode(encryptField.encode() == EncodeType.DEFAULT ? defaultProperties.getEncode() : encryptField.encode()); |
| | | encryptContext.setPassword(StringUtils.isBlank(encryptField.password()) ? defaultProperties.getPassword() : encryptField.password()); |
| | | encryptContext.setPrivateKey(StringUtils.isBlank(encryptField.privateKey()) ? defaultProperties.getPrivateKey() : encryptField.privateKey()); |
| | | encryptContext.setPublicKey(StringUtils.isBlank(encryptField.publicKey()) ? defaultProperties.getPublicKey() : encryptField.publicKey()); |
| | | return this.encryptorManager.decrypt(value, encryptContext); |
| | | } |
| | | |
| | | @Override |
| | | public Object plugin(Object target) { |
| | | return Plugin.wrap(target, this); |
| | | } |
| | | |
| | | @Override |
| | | public void setProperties(Properties properties) { |
| | | |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.interceptor; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.ibatis.executor.parameter.ParameterHandler; |
| | | import org.apache.ibatis.plugin.Interceptor; |
| | | import org.apache.ibatis.plugin.Intercepts; |
| | | import org.apache.ibatis.plugin.Invocation; |
| | | import org.apache.ibatis.plugin.Signature; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.encrypt.annotation.EncryptField; |
| | | import org.dromara.common.encrypt.core.EncryptContext; |
| | | import org.dromara.common.encrypt.core.EncryptorManager; |
| | | import org.dromara.common.encrypt.enumd.AlgorithmType; |
| | | import org.dromara.common.encrypt.enumd.EncodeType; |
| | | import org.dromara.common.encrypt.properties.EncryptorProperties; |
| | | |
| | | import java.lang.reflect.Field; |
| | | import java.sql.PreparedStatement; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * å
¥åå 坿¦æªå¨ |
| | | * |
| | | * @author è马 |
| | | * @version 4.6.0 |
| | | */ |
| | | @Slf4j |
| | | @Intercepts({@Signature( |
| | | type = ParameterHandler.class, |
| | | method = "setParameters", |
| | | args = {PreparedStatement.class}) |
| | | }) |
| | | @AllArgsConstructor |
| | | public class MybatisEncryptInterceptor implements Interceptor { |
| | | |
| | | private final EncryptorManager encryptorManager; |
| | | private final EncryptorProperties defaultProperties; |
| | | |
| | | @Override |
| | | public Object intercept(Invocation invocation) throws Throwable { |
| | | return invocation; |
| | | } |
| | | |
| | | @Override |
| | | public Object plugin(Object target) { |
| | | if (target instanceof ParameterHandler parameterHandler) { |
| | | // è¿è¡å å¯æä½ |
| | | Object parameterObject = parameterHandler.getParameterObject(); |
| | | if (ObjectUtil.isNotNull(parameterObject) && !(parameterObject instanceof String)) { |
| | | this.encryptHandler(parameterObject); |
| | | } |
| | | } |
| | | return target; |
| | | } |
| | | |
| | | /** |
| | | * å å¯å¯¹è±¡ |
| | | * |
| | | * @param sourceObject å¾
å å¯å¯¹è±¡ |
| | | */ |
| | | private void encryptHandler(Object sourceObject) { |
| | | if (ObjectUtil.isNull(sourceObject)) { |
| | | return; |
| | | } |
| | | if (sourceObject instanceof Map<?, ?> map) { |
| | | new HashSet<>(map.values()).forEach(this::encryptHandler); |
| | | return; |
| | | } |
| | | if (sourceObject instanceof List<?> list) { |
| | | if(CollUtil.isEmpty(list)) { |
| | | return; |
| | | } |
| | | // å¤æç¬¬ä¸ä¸ªå
ç´ æ¯å¦å«ææ³¨è§£ãå¦ææ²¡æç´æ¥è¿åï¼æé«æç |
| | | Object firstItem = list.get(0); |
| | | if (ObjectUtil.isNull(firstItem) || CollUtil.isEmpty(encryptorManager.getFieldCache(firstItem.getClass()))) { |
| | | return; |
| | | } |
| | | list.forEach(this::encryptHandler); |
| | | return; |
| | | } |
| | | // ä¸å¨ç¼åä¸çç±»,å°±æ¯æ²¡æå 坿³¨è§£çç±»(å½ç¶ä¹æå¯è½æ¯typeAliasesPackageåé) |
| | | Set<Field> fields = encryptorManager.getFieldCache(sourceObject.getClass()); |
| | | if(ObjectUtil.isNull(fields)){ |
| | | return; |
| | | } |
| | | try { |
| | | for (Field field : fields) { |
| | | field.set(sourceObject, this.encryptField(Convert.toStr(field.get(sourceObject)), field)); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("å¤çå å¯å段æ¶åºé", e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * åæ®µå¼è¿è¡å å¯ãéè¿åæ®µçæ¹æ³¨æ³¨åæ°çå å¯ç®æ³ |
| | | * |
| | | * @param value å¾
å å¯çå¼ |
| | | * @param field å¾
å å¯å段 |
| | | * @return å å¯åç»æ |
| | | */ |
| | | private String encryptField(String value, Field field) { |
| | | if (ObjectUtil.isNull(value)) { |
| | | return null; |
| | | } |
| | | EncryptField encryptField = field.getAnnotation(EncryptField.class); |
| | | EncryptContext encryptContext = new EncryptContext(); |
| | | encryptContext.setAlgorithm(encryptField.algorithm() == AlgorithmType.DEFAULT ? defaultProperties.getAlgorithm() : encryptField.algorithm()); |
| | | encryptContext.setEncode(encryptField.encode() == EncodeType.DEFAULT ? defaultProperties.getEncode() : encryptField.encode()); |
| | | encryptContext.setPassword(StringUtils.isBlank(encryptField.password()) ? defaultProperties.getPassword() : encryptField.password()); |
| | | encryptContext.setPrivateKey(StringUtils.isBlank(encryptField.privateKey()) ? defaultProperties.getPrivateKey() : encryptField.privateKey()); |
| | | encryptContext.setPublicKey(StringUtils.isBlank(encryptField.publicKey()) ? defaultProperties.getPublicKey() : encryptField.publicKey()); |
| | | return this.encryptorManager.encrypt(value, encryptContext); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public void setProperties(Properties properties) { |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.properties; |
| | | |
| | | import lombok.Data; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | |
| | | /** |
| | | * apiè§£å¯å±æ§é
置类 |
| | | * @author wdhcr |
| | | */ |
| | | @Data |
| | | @ConfigurationProperties(prefix = "api-decrypt") |
| | | public class ApiDecryptProperties { |
| | | |
| | | /** |
| | | * å å¯å¼å
³ |
| | | */ |
| | | private Boolean enabled; |
| | | |
| | | /** |
| | | * 头鍿 è¯ |
| | | */ |
| | | private String headerFlag; |
| | | |
| | | /** |
| | | * ååºå å¯å
¬é¥ |
| | | */ |
| | | private String publicKey; |
| | | |
| | | /** |
| | | * 请æ±è§£å¯ç§é¥ |
| | | */ |
| | | private String privateKey; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.properties; |
| | | |
| | | import org.dromara.common.encrypt.enumd.AlgorithmType; |
| | | import org.dromara.common.encrypt.enumd.EncodeType; |
| | | import lombok.Data; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | |
| | | /** |
| | | * å è§£å¯å±æ§é
置类 |
| | | * |
| | | * @author è马 |
| | | * @version 4.6.0 |
| | | */ |
| | | @Data |
| | | @ConfigurationProperties(prefix = "mybatis-encryptor") |
| | | public class EncryptorProperties { |
| | | |
| | | /** |
| | | * è¿æ»¤å¼å
³ |
| | | */ |
| | | private Boolean enable; |
| | | |
| | | /** |
| | | * é»è®¤ç®æ³ |
| | | */ |
| | | private AlgorithmType algorithm; |
| | | |
| | | /** |
| | | * å®å
¨ç§é¥ |
| | | */ |
| | | private String password; |
| | | |
| | | /** |
| | | * å
¬é¥ |
| | | */ |
| | | private String publicKey; |
| | | |
| | | /** |
| | | * ç§é¥ |
| | | */ |
| | | private String privateKey; |
| | | |
| | | /** |
| | | * ç¼ç æ¹å¼ï¼base64/hex |
| | | */ |
| | | private EncodeType encode; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.encrypt.utils; |
| | | |
| | | import cn.hutool.core.codec.Base64; |
| | | import cn.hutool.core.util.ArrayUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.hutool.crypto.SecureUtil; |
| | | import cn.hutool.crypto.SmUtil; |
| | | import cn.hutool.crypto.asymmetric.KeyType; |
| | | import cn.hutool.crypto.asymmetric.RSA; |
| | | import cn.hutool.crypto.asymmetric.SM2; |
| | | |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * å®å
¨ç¸å
³å·¥å
·ç±» |
| | | * |
| | | * @author è马 |
| | | */ |
| | | public class EncryptUtils { |
| | | |
| | | /** |
| | | * å
¬é¥ |
| | | */ |
| | | public static final String PUBLIC_KEY = "publicKey"; |
| | | |
| | | /** |
| | | * ç§é¥ |
| | | */ |
| | | public static final String PRIVATE_KEY = "privateKey"; |
| | | |
| | | /** |
| | | * Base64å å¯ |
| | | * |
| | | * @param data å¾
å 坿°æ® |
| | | * @return å å¯åå符串 |
| | | */ |
| | | public static String encryptByBase64(String data) { |
| | | return Base64.encode(data, StandardCharsets.UTF_8); |
| | | } |
| | | |
| | | /** |
| | | * Base64è§£å¯ |
| | | * |
| | | * @param data å¾
è§£å¯æ°æ® |
| | | * @return è§£å¯åå符串 |
| | | */ |
| | | public static String decryptByBase64(String data) { |
| | | return Base64.decodeStr(data, StandardCharsets.UTF_8); |
| | | } |
| | | |
| | | /** |
| | | * AESå å¯ |
| | | * |
| | | * @param data å¾
å 坿°æ® |
| | | * @param password ç§é¥å符串 |
| | | * @return å å¯åå符串, éç¨Base64ç¼ç |
| | | */ |
| | | public static String encryptByAes(String data, String password) { |
| | | if (StrUtil.isBlank(password)) { |
| | | throw new IllegalArgumentException("AESéè¦ä¼ å
¥ç§é¥ä¿¡æ¯"); |
| | | } |
| | | // aesç®æ³çç§é¥è¦æ±æ¯16ä½ã24ä½ã32ä½ |
| | | int[] array = {16, 24, 32}; |
| | | if (!ArrayUtil.contains(array, password.length())) { |
| | | throw new IllegalArgumentException("AESç§é¥é¿åº¦è¦æ±ä¸º16ä½ã24ä½ã32ä½"); |
| | | } |
| | | return SecureUtil.aes(password.getBytes(StandardCharsets.UTF_8)).encryptBase64(data, StandardCharsets.UTF_8); |
| | | } |
| | | |
| | | /** |
| | | * AESå å¯ |
| | | * |
| | | * @param data å¾
å 坿°æ® |
| | | * @param password ç§é¥å符串 |
| | | * @return å å¯åå符串, éç¨Hexç¼ç |
| | | */ |
| | | public static String encryptByAesHex(String data, String password) { |
| | | if (StrUtil.isBlank(password)) { |
| | | throw new IllegalArgumentException("AESéè¦ä¼ å
¥ç§é¥ä¿¡æ¯"); |
| | | } |
| | | // aesç®æ³çç§é¥è¦æ±æ¯16ä½ã24ä½ã32ä½ |
| | | int[] array = {16, 24, 32}; |
| | | if (!ArrayUtil.contains(array, password.length())) { |
| | | throw new IllegalArgumentException("AESç§é¥é¿åº¦è¦æ±ä¸º16ä½ã24ä½ã32ä½"); |
| | | } |
| | | return SecureUtil.aes(password.getBytes(StandardCharsets.UTF_8)).encryptHex(data, StandardCharsets.UTF_8); |
| | | } |
| | | |
| | | /** |
| | | * AESè§£å¯ |
| | | * |
| | | * @param data å¾
è§£å¯æ°æ® |
| | | * @param password ç§é¥å符串 |
| | | * @return è§£å¯åå符串 |
| | | */ |
| | | public static String decryptByAes(String data, String password) { |
| | | if (StrUtil.isBlank(password)) { |
| | | throw new IllegalArgumentException("AESéè¦ä¼ å
¥ç§é¥ä¿¡æ¯"); |
| | | } |
| | | // aesç®æ³çç§é¥è¦æ±æ¯16ä½ã24ä½ã32ä½ |
| | | int[] array = {16, 24, 32}; |
| | | if (!ArrayUtil.contains(array, password.length())) { |
| | | throw new IllegalArgumentException("AESç§é¥é¿åº¦è¦æ±ä¸º16ä½ã24ä½ã32ä½"); |
| | | } |
| | | return SecureUtil.aes(password.getBytes(StandardCharsets.UTF_8)).decryptStr(data, StandardCharsets.UTF_8); |
| | | } |
| | | |
| | | /** |
| | | * SM4å å¯ï¼Base64ç¼ç ï¼ |
| | | * |
| | | * @param data å¾
å 坿°æ® |
| | | * @param password ç§é¥å符串 |
| | | * @return å å¯åå符串, éç¨Base64ç¼ç |
| | | */ |
| | | public static String encryptBySm4(String data, String password) { |
| | | if (StrUtil.isBlank(password)) { |
| | | throw new IllegalArgumentException("SM4éè¦ä¼ å
¥ç§é¥ä¿¡æ¯"); |
| | | } |
| | | // sm4ç®æ³çç§é¥è¦æ±æ¯16ä½é¿åº¦ |
| | | int sm4PasswordLength = 16; |
| | | if (sm4PasswordLength != password.length()) { |
| | | throw new IllegalArgumentException("SM4ç§é¥é¿åº¦è¦æ±ä¸º16ä½"); |
| | | } |
| | | return SmUtil.sm4(password.getBytes(StandardCharsets.UTF_8)).encryptBase64(data, StandardCharsets.UTF_8); |
| | | } |
| | | |
| | | /** |
| | | * SM4å å¯ï¼Hexç¼ç ï¼ |
| | | * |
| | | * @param data å¾
å 坿°æ® |
| | | * @param password ç§é¥å符串 |
| | | * @return å å¯åå符串, éç¨Hexç¼ç |
| | | */ |
| | | public static String encryptBySm4Hex(String data, String password) { |
| | | if (StrUtil.isBlank(password)) { |
| | | throw new IllegalArgumentException("SM4éè¦ä¼ å
¥ç§é¥ä¿¡æ¯"); |
| | | } |
| | | // sm4ç®æ³çç§é¥è¦æ±æ¯16ä½é¿åº¦ |
| | | int sm4PasswordLength = 16; |
| | | if (sm4PasswordLength != password.length()) { |
| | | throw new IllegalArgumentException("SM4ç§é¥é¿åº¦è¦æ±ä¸º16ä½"); |
| | | } |
| | | return SmUtil.sm4(password.getBytes(StandardCharsets.UTF_8)).encryptHex(data, StandardCharsets.UTF_8); |
| | | } |
| | | |
| | | /** |
| | | * sm4è§£å¯ |
| | | * |
| | | * @param data å¾
è§£å¯æ°æ®ï¼å¯ä»¥æ¯Base64æHexç¼ç ï¼ |
| | | * @param password ç§é¥å符串 |
| | | * @return è§£å¯åå符串 |
| | | */ |
| | | public static String decryptBySm4(String data, String password) { |
| | | if (StrUtil.isBlank(password)) { |
| | | throw new IllegalArgumentException("SM4éè¦ä¼ å
¥ç§é¥ä¿¡æ¯"); |
| | | } |
| | | // sm4ç®æ³çç§é¥è¦æ±æ¯16ä½é¿åº¦ |
| | | int sm4PasswordLength = 16; |
| | | if (sm4PasswordLength != password.length()) { |
| | | throw new IllegalArgumentException("SM4ç§é¥é¿åº¦è¦æ±ä¸º16ä½"); |
| | | } |
| | | return SmUtil.sm4(password.getBytes(StandardCharsets.UTF_8)).decryptStr(data, StandardCharsets.UTF_8); |
| | | } |
| | | |
| | | /** |
| | | * 产çsm2å è§£å¯éè¦çå
¬é¥åç§é¥ |
| | | * |
| | | * @return å
¬ç§é¥Map |
| | | */ |
| | | public static Map<String, String> generateSm2Key() { |
| | | Map<String, String> keyMap = new HashMap<>(2); |
| | | SM2 sm2 = SmUtil.sm2(); |
| | | keyMap.put(PRIVATE_KEY, sm2.getPrivateKeyBase64()); |
| | | keyMap.put(PUBLIC_KEY, sm2.getPublicKeyBase64()); |
| | | return keyMap; |
| | | } |
| | | |
| | | /** |
| | | * sm2å
¬é¥å å¯ |
| | | * |
| | | * @param data å¾
å 坿°æ® |
| | | * @param publicKey å
¬é¥ |
| | | * @return å å¯åå符串, éç¨Base64ç¼ç |
| | | */ |
| | | public static String encryptBySm2(String data, String publicKey) { |
| | | if (StrUtil.isBlank(publicKey)) { |
| | | throw new IllegalArgumentException("SM2éè¦ä¼ å
¥å
¬é¥è¿è¡å å¯"); |
| | | } |
| | | SM2 sm2 = SmUtil.sm2(null, publicKey); |
| | | return sm2.encryptBase64(data, StandardCharsets.UTF_8, KeyType.PublicKey); |
| | | } |
| | | |
| | | /** |
| | | * sm2å
¬é¥å å¯ |
| | | * |
| | | * @param data å¾
å 坿°æ® |
| | | * @param publicKey å
¬é¥ |
| | | * @return å å¯åå符串, éç¨Hexç¼ç |
| | | */ |
| | | public static String encryptBySm2Hex(String data, String publicKey) { |
| | | if (StrUtil.isBlank(publicKey)) { |
| | | throw new IllegalArgumentException("SM2éè¦ä¼ å
¥å
¬é¥è¿è¡å å¯"); |
| | | } |
| | | SM2 sm2 = SmUtil.sm2(null, publicKey); |
| | | return sm2.encryptHex(data, StandardCharsets.UTF_8, KeyType.PublicKey); |
| | | } |
| | | |
| | | /** |
| | | * sm2ç§é¥è§£å¯ |
| | | * |
| | | * @param data å¾
è§£å¯æ°æ® |
| | | * @param privateKey ç§é¥ |
| | | * @return è§£å¯åå符串 |
| | | */ |
| | | public static String decryptBySm2(String data, String privateKey) { |
| | | if (StrUtil.isBlank(privateKey)) { |
| | | throw new IllegalArgumentException("SM2éè¦ä¼ å
¥ç§é¥è¿è¡è§£å¯"); |
| | | } |
| | | SM2 sm2 = SmUtil.sm2(privateKey, null); |
| | | return sm2.decryptStr(data, KeyType.PrivateKey, StandardCharsets.UTF_8); |
| | | } |
| | | |
| | | /** |
| | | * 产çRSAå è§£å¯éè¦çå
¬é¥åç§é¥ |
| | | * |
| | | * @return å
¬ç§é¥Map |
| | | */ |
| | | public static Map<String, String> generateRsaKey() { |
| | | Map<String, String> keyMap = new HashMap<>(2); |
| | | RSA rsa = SecureUtil.rsa(); |
| | | keyMap.put(PRIVATE_KEY, rsa.getPrivateKeyBase64()); |
| | | keyMap.put(PUBLIC_KEY, rsa.getPublicKeyBase64()); |
| | | return keyMap; |
| | | } |
| | | |
| | | /** |
| | | * rsaå
¬é¥å å¯ |
| | | * |
| | | * @param data å¾
å 坿°æ® |
| | | * @param publicKey å
¬é¥ |
| | | * @return å å¯åå符串, éç¨Base64ç¼ç |
| | | */ |
| | | public static String encryptByRsa(String data, String publicKey) { |
| | | if (StrUtil.isBlank(publicKey)) { |
| | | throw new IllegalArgumentException("RSAéè¦ä¼ å
¥å
¬é¥è¿è¡å å¯"); |
| | | } |
| | | RSA rsa = SecureUtil.rsa(null, publicKey); |
| | | return rsa.encryptBase64(data, StandardCharsets.UTF_8, KeyType.PublicKey); |
| | | } |
| | | |
| | | /** |
| | | * rsaå
¬é¥å å¯ |
| | | * |
| | | * @param data å¾
å 坿°æ® |
| | | * @param publicKey å
¬é¥ |
| | | * @return å å¯åå符串, éç¨Hexç¼ç |
| | | */ |
| | | public static String encryptByRsaHex(String data, String publicKey) { |
| | | if (StrUtil.isBlank(publicKey)) { |
| | | throw new IllegalArgumentException("RSAéè¦ä¼ å
¥å
¬é¥è¿è¡å å¯"); |
| | | } |
| | | RSA rsa = SecureUtil.rsa(null, publicKey); |
| | | return rsa.encryptHex(data, StandardCharsets.UTF_8, KeyType.PublicKey); |
| | | } |
| | | |
| | | /** |
| | | * rsaç§é¥è§£å¯ |
| | | * |
| | | * @param data å¾
è§£å¯æ°æ® |
| | | * @param privateKey ç§é¥ |
| | | * @return è§£å¯åå符串 |
| | | */ |
| | | public static String decryptByRsa(String data, String privateKey) { |
| | | if (StrUtil.isBlank(privateKey)) { |
| | | throw new IllegalArgumentException("RSAéè¦ä¼ å
¥ç§é¥è¿è¡è§£å¯"); |
| | | } |
| | | RSA rsa = SecureUtil.rsa(privateKey, null); |
| | | return rsa.decryptStr(data, KeyType.PrivateKey, StandardCharsets.UTF_8); |
| | | } |
| | | |
| | | /** |
| | | * md5å å¯ |
| | | * |
| | | * @param data å¾
å 坿°æ® |
| | | * @return å å¯åå符串, éç¨Hexç¼ç |
| | | */ |
| | | public static String encryptByMd5(String data) { |
| | | return SecureUtil.md5(data); |
| | | } |
| | | |
| | | /** |
| | | * sha256å å¯ |
| | | * |
| | | * @param data å¾
å 坿°æ® |
| | | * @return å å¯åå符串, éç¨Hexç¼ç |
| | | */ |
| | | public static String encryptBySha256(String data) { |
| | | return SecureUtil.sha256(data); |
| | | } |
| | | |
| | | /** |
| | | * sm3å å¯ |
| | | * |
| | | * @param data å¾
å 坿°æ® |
| | | * @return å å¯åå符串, éç¨Hexç¼ç |
| | | */ |
| | | public static String encryptBySm3(String data) { |
| | | return SmUtil.sm3(data); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | org.dromara.common.encrypt.config.EncryptorAutoConfiguration |
| | | org.dromara.common.encrypt.config.ApiDecryptAutoConfiguration |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>5.5.3</version> |
| | | </parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-excel</artifactId> |
| | | <version>5.5.3</version> |
| | | <description>ruoyi-common-excel</description> |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-json</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>cn.idev.excel</groupId> |
| | | <artifactId>fastexcel</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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"> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>${revision}</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>ruoyi-common-excel</artifactId> |
| | | |
| | | <description> |
| | | ruoyi-common-excel |
| | | </description> |
| | | |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-json</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>cn.idev.excel</groupId> |
| | | <artifactId>fastexcel</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.annotation; |
| | | |
| | | import org.dromara.common.excel.core.CellMergeStrategy; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * excel ååå
æ ¼åå¹¶(åå¹¶åç¸å项) |
| | | * |
| | | * éæé
{@link CellMergeStrategy} çç¥ä½¿ç¨ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Target(ElementType.FIELD) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @Inherited |
| | | public @interface CellMerge { |
| | | |
| | | /** |
| | | * col index |
| | | */ |
| | | int index() default -1; |
| | | |
| | | /** |
| | | * åå¹¶éè¦ä¾èµçå
¶ä»å段åç§° |
| | | */ |
| | | String[] mergeBy() default {}; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.annotation; |
| | | |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * åå
¸æ ¼å¼å |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Target({ElementType.FIELD}) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @Inherited |
| | | public @interface ExcelDictFormat { |
| | | |
| | | /** |
| | | * 妿æ¯åå
¸ç±»åï¼è¯·è®¾ç½®åå
¸çtypeå¼ (å¦: sys_user_sex) |
| | | */ |
| | | String dictType() default ""; |
| | | |
| | | /** |
| | | * 读åå
å®¹è½¬è¡¨è¾¾å¼ (å¦: 0=ç·,1=女,2=æªç¥) |
| | | */ |
| | | String readConverterExp() default ""; |
| | | |
| | | /** |
| | | * åé符ï¼è¯»åå符串ç»å
容 |
| | | */ |
| | | String separator() default StringUtils.SEPARATOR; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.annotation; |
| | | |
| | | import org.dromara.common.excel.core.ExcelOptionsProvider; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * Excel卿䏿é项注解 |
| | | * |
| | | * @author Angus |
| | | */ |
| | | @Target({ElementType.FIELD}) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @Inherited |
| | | public @interface ExcelDynamicOptions { |
| | | |
| | | /** |
| | | * æä¾è
ç±»å
¨éå®å |
| | | * <p> |
| | | * {@link org.dromara.common.excel.core.ExcelOptionsProvider} æ¥å£å®ç°ç±» class |
| | | */ |
| | | Class<? extends ExcelOptionsProvider> providerClass(); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.annotation; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * æä¸¾æ ¼å¼å |
| | | * |
| | | * @author Liang |
| | | */ |
| | | @Target({ElementType.FIELD}) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @Inherited |
| | | public @interface ExcelEnumFormat { |
| | | |
| | | /** |
| | | * åå
¸æä¸¾ç±»å |
| | | */ |
| | | Class<? extends Enum<?>> enumClass(); |
| | | |
| | | /** |
| | | * åå
¸æä¸¾ç±»ä¸å¯¹åºçcode屿§åç§°ï¼é»è®¤ä¸ºcode |
| | | */ |
| | | String codeField() default "code"; |
| | | |
| | | /** |
| | | * åå
¸æä¸¾ç±»ä¸å¯¹åºçtext屿§åç§°ï¼é»è®¤ä¸ºtext |
| | | */ |
| | | String textField() default "text"; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.annotation; |
| | | |
| | | import java.lang.annotation.ElementType; |
| | | import java.lang.annotation.Retention; |
| | | import java.lang.annotation.RetentionPolicy; |
| | | import java.lang.annotation.Target; |
| | | |
| | | /** |
| | | * æ¹æ³¨ æ¤æ³¨è§£ä»
ç¨äºå表头 䏿¯æå¤å±çº§è¡¨å¤´ |
| | | * @author guzhouyanyu |
| | | */ |
| | | @Target({ElementType.FIELD}) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | public @interface ExcelNotation { |
| | | |
| | | /** |
| | | * æ¹æ³¨å
容 |
| | | */ |
| | | String value() default ""; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.annotation; |
| | | |
| | | import org.apache.poi.ss.usermodel.IndexedColors; |
| | | |
| | | import java.lang.annotation.ElementType; |
| | | import java.lang.annotation.Retention; |
| | | import java.lang.annotation.RetentionPolicy; |
| | | import java.lang.annotation.Target; |
| | | |
| | | /** |
| | | * æ¯å¦å¿
å¡« æ¤æ³¨è§£ä»
ç¨äºå表头 䏿¯æå¤å±çº§è¡¨å¤´ |
| | | * @author guzhouyanyu |
| | | */ |
| | | @Target({ElementType.FIELD}) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | public @interface ExcelRequired { |
| | | |
| | | /** |
| | | * åä½é¢è² |
| | | */ |
| | | IndexedColors fontColor() default IndexedColors.RED; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.convert; |
| | | |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import cn.idev.excel.converters.Converter; |
| | | import cn.idev.excel.enums.CellDataTypeEnum; |
| | | import cn.idev.excel.metadata.GlobalConfiguration; |
| | | import cn.idev.excel.metadata.data.ReadCellData; |
| | | import cn.idev.excel.metadata.data.WriteCellData; |
| | | import cn.idev.excel.metadata.property.ExcelContentProperty; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | |
| | | import java.math.BigDecimal; |
| | | |
| | | /** |
| | | * 大æ°å¼è½¬æ¢ |
| | | * Excel æ°å¼é¿åº¦ä½15ä½ å¤§äº15ä½çæ°å¼è½¬æ¢ä½å符串 |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Slf4j |
| | | public class ExcelBigNumberConvert implements Converter<Long> { |
| | | |
| | | @Override |
| | | public Class<Long> supportJavaTypeKey() { |
| | | return Long.class; |
| | | } |
| | | |
| | | @Override |
| | | public CellDataTypeEnum supportExcelTypeKey() { |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public Long convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { |
| | | return Convert.toLong(cellData.getData()); |
| | | } |
| | | |
| | | @Override |
| | | public WriteCellData<Object> convertToExcelData(Long object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { |
| | | if (ObjectUtil.isNotNull(object)) { |
| | | String str = Convert.toStr(object); |
| | | if (str.length() > 15) { |
| | | return new WriteCellData<>(str); |
| | | } |
| | | } |
| | | WriteCellData<Object> cellData = new WriteCellData<>(new BigDecimal(object)); |
| | | cellData.setType(CellDataTypeEnum.NUMBER); |
| | | return cellData; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.convert; |
| | | |
| | | import cn.hutool.core.annotation.AnnotationUtil; |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import cn.idev.excel.converters.Converter; |
| | | import cn.idev.excel.enums.CellDataTypeEnum; |
| | | import cn.idev.excel.metadata.GlobalConfiguration; |
| | | import cn.idev.excel.metadata.data.ReadCellData; |
| | | import cn.idev.excel.metadata.data.WriteCellData; |
| | | import cn.idev.excel.metadata.property.ExcelContentProperty; |
| | | import org.dromara.common.excel.annotation.ExcelDictFormat; |
| | | import org.dromara.common.core.service.DictService; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.excel.utils.ExcelUtil; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | |
| | | import java.lang.reflect.Field; |
| | | |
| | | /** |
| | | * åå
¸æ ¼å¼å转æ¢å¤ç |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Slf4j |
| | | public class ExcelDictConvert implements Converter<Object> { |
| | | |
| | | @Override |
| | | public Class<Object> supportJavaTypeKey() { |
| | | return Object.class; |
| | | } |
| | | |
| | | @Override |
| | | public CellDataTypeEnum supportExcelTypeKey() { |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public Object convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { |
| | | ExcelDictFormat anno = getAnnotation(contentProperty.getField()); |
| | | String type = anno.dictType(); |
| | | String label = cellData.getStringValue(); |
| | | String value; |
| | | if (StringUtils.isBlank(type)) { |
| | | value = ExcelUtil.reverseByExp(label, anno.readConverterExp(), anno.separator()); |
| | | } else { |
| | | value = SpringUtils.getBean(DictService.class).getDictValue(type, label, anno.separator()); |
| | | } |
| | | return Convert.convert(contentProperty.getField().getType(), value); |
| | | } |
| | | |
| | | @Override |
| | | public WriteCellData<String> convertToExcelData(Object object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { |
| | | if (ObjectUtil.isNull(object)) { |
| | | return new WriteCellData<>(""); |
| | | } |
| | | ExcelDictFormat anno = getAnnotation(contentProperty.getField()); |
| | | String type = anno.dictType(); |
| | | String value = Convert.toStr(object); |
| | | String label; |
| | | if (StringUtils.isBlank(type)) { |
| | | label = ExcelUtil.convertByExp(value, anno.readConverterExp(), anno.separator()); |
| | | } else { |
| | | label = SpringUtils.getBean(DictService.class).getDictLabel(type, value, anno.separator()); |
| | | } |
| | | return new WriteCellData<>(label); |
| | | } |
| | | |
| | | private ExcelDictFormat getAnnotation(Field field) { |
| | | return AnnotationUtil.getAnnotation(field, ExcelDictFormat.class); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.convert; |
| | | |
| | | import cn.hutool.core.annotation.AnnotationUtil; |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import cn.idev.excel.converters.Converter; |
| | | import cn.idev.excel.enums.CellDataTypeEnum; |
| | | import cn.idev.excel.metadata.GlobalConfiguration; |
| | | import cn.idev.excel.metadata.data.ReadCellData; |
| | | import cn.idev.excel.metadata.data.WriteCellData; |
| | | import cn.idev.excel.metadata.property.ExcelContentProperty; |
| | | import org.dromara.common.core.utils.reflect.ReflectUtils; |
| | | import org.dromara.common.excel.annotation.ExcelEnumFormat; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | |
| | | import java.lang.reflect.Field; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * æä¸¾æ ¼å¼å转æ¢å¤ç |
| | | * |
| | | * @author Liang |
| | | */ |
| | | @Slf4j |
| | | public class ExcelEnumConvert implements Converter<Object> { |
| | | |
| | | @Override |
| | | public Class<Object> supportJavaTypeKey() { |
| | | return Object.class; |
| | | } |
| | | |
| | | @Override |
| | | public CellDataTypeEnum supportExcelTypeKey() { |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public Object convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { |
| | | cellData.checkEmpty(); |
| | | // Excelä¸å¡«å
¥çæ¯æä¸¾ä¸æå®çæè¿° |
| | | Object textValue = switch (cellData.getType()) { |
| | | case STRING, DIRECT_STRING, RICH_TEXT_STRING -> cellData.getStringValue(); |
| | | case NUMBER -> cellData.getNumberValue(); |
| | | case BOOLEAN -> cellData.getBooleanValue(); |
| | | default -> throw new IllegalArgumentException("åå
æ ¼ç±»åå¼å¸¸!"); |
| | | }; |
| | | // 妿æ¯ç©ºå¼ |
| | | if (ObjectUtil.isNull(textValue)) { |
| | | return null; |
| | | } |
| | | Map<Object, String> enumCodeToTextMap = beforeConvert(contentProperty); |
| | | // ä»Javaè¾åºè³Excelæ¯code转text |
| | | // å æ¤ä»Excel转Javaåºè¯¥å°textä¸codeå¯¹è° |
| | | Map<Object, Object> enumTextToCodeMap = new HashMap<>(); |
| | | enumCodeToTextMap.forEach((key, value) -> enumTextToCodeMap.put(value, key)); |
| | | // åºè¯¥ä»text -> code䏿¥æ¾ |
| | | Object codeValue = enumTextToCodeMap.get(textValue); |
| | | return Convert.convert(contentProperty.getField().getType(), codeValue); |
| | | } |
| | | |
| | | @Override |
| | | public WriteCellData<String> convertToExcelData(Object object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) { |
| | | if (ObjectUtil.isNull(object)) { |
| | | return new WriteCellData<>(""); |
| | | } |
| | | Map<Object, String> enumValueMap = beforeConvert(contentProperty); |
| | | String value = Convert.toStr(enumValueMap.get(object), ""); |
| | | return new WriteCellData<>(value); |
| | | } |
| | | |
| | | private Map<Object, String> beforeConvert(ExcelContentProperty contentProperty) { |
| | | ExcelEnumFormat anno = getAnnotation(contentProperty.getField()); |
| | | Map<Object, String> enumValueMap = new HashMap<>(); |
| | | Enum<?>[] enumConstants = anno.enumClass().getEnumConstants(); |
| | | for (Enum<?> enumConstant : enumConstants) { |
| | | Object codeValue = ReflectUtils.invokeGetter(enumConstant, anno.codeField()); |
| | | String textValue = ReflectUtils.invokeGetter(enumConstant, anno.textField()); |
| | | enumValueMap.put(codeValue, textValue); |
| | | } |
| | | return enumValueMap; |
| | | } |
| | | |
| | | private ExcelEnumFormat getAnnotation(Field field) { |
| | | return AnnotationUtil.getAnnotation(field, ExcelEnumFormat.class); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.core; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ReflectUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.idev.excel.annotation.ExcelIgnore; |
| | | import cn.idev.excel.annotation.ExcelIgnoreUnannotated; |
| | | import cn.idev.excel.annotation.ExcelProperty; |
| | | import lombok.SneakyThrows; |
| | | import org.apache.poi.ss.util.CellRangeAddress; |
| | | import org.dromara.common.core.utils.reflect.ReflectUtils; |
| | | import org.dromara.common.excel.annotation.CellMerge; |
| | | |
| | | import java.lang.reflect.Field; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * åå
æ ¼åå¹¶å¤çå¨ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public class CellMergeHandler { |
| | | |
| | | private final boolean hasTitle; |
| | | private int rowIndex; |
| | | |
| | | private CellMergeHandler(final boolean hasTitle) { |
| | | this.hasTitle = hasTitle; |
| | | // è¡åå¹¶å¼å§ä¸æ |
| | | this.rowIndex = hasTitle ? 1 : 0; |
| | | } |
| | | private CellMergeHandler(final boolean hasTitle, final int rowIndex) { |
| | | this.hasTitle = hasTitle; |
| | | this.rowIndex = hasTitle ? rowIndex : 0; |
| | | } |
| | | @SneakyThrows |
| | | public List<CellRangeAddress> handle(List<?> rows) { |
| | | // 妿å
¥å为空éååè¿å空é |
| | | if (CollUtil.isEmpty(rows)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | |
| | | // è·åæå并注解çåæ®µ |
| | | Map<Field, FieldColumnIndex> mergeFields = getFieldColumnIndexMap(rows.get(0).getClass()); |
| | | // å¦ææ²¡æéè¦åå¹¶çåæ®µåè¿å空é |
| | | if (CollUtil.isEmpty(mergeFields)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | |
| | | // ç»æé |
| | | List<CellRangeAddress> result = new ArrayList<>(); |
| | | |
| | | // çæä¸¤ä¸¤åå¹¶åå
æ ¼ |
| | | Map<Field, RepeatCell> rowRepeatCellMap = new HashMap<>(); |
| | | for (Map.Entry<Field, FieldColumnIndex> item : mergeFields.entrySet()) { |
| | | Field field = item.getKey(); |
| | | FieldColumnIndex itemValue = item.getValue(); |
| | | int colNum = itemValue.colIndex(); |
| | | CellMerge cellMerge = itemValue.cellMerge(); |
| | | |
| | | for (int i = 0; i < rows.size(); i++) { |
| | | // å½åè¡æ°æ® |
| | | Object currentRowObj = rows.get(i); |
| | | // å½åè¡æ°æ®åæ®µå¼ |
| | | Object currentRowObjFieldVal = ReflectUtils.invokeGetter(currentRowObj, field.getName()); |
| | | |
| | | // 空å¼è·³è¿ä¸å¤ç |
| | | if (currentRowObjFieldVal == null || "".equals(currentRowObjFieldVal)) { |
| | | continue; |
| | | } |
| | | |
| | | // åå
æ ¼åå¹¶Mapæ¯å¦å卿°æ®ï¼å¦æä¸åå¨åæ·»å å½åè¡çåæ®µå¼ |
| | | if (!rowRepeatCellMap.containsKey(field)) { |
| | | rowRepeatCellMap.put(field, RepeatCell.of(currentRowObjFieldVal, i)); |
| | | continue; |
| | | } |
| | | |
| | | // è·å åå
æ ¼åå¹¶Map ä¸åæ®µå¼ |
| | | RepeatCell repeatCell = rowRepeatCellMap.get(field); |
| | | Object cellValue = repeatCell.value(); |
| | | int current = repeatCell.current(); |
| | | |
| | | // æ£æ¥æ¯å¦æ»¡è¶³åå¹¶æ¡ä»¶ |
| | | // currentRowObj å½åè¡æ°æ® |
| | | // rows.get(i - 1) ä¸ä¸è¡æ°æ® 注ï¼ç±äº if (!rowRepeatCellMap.containsKey(field)) æ¡ä»¶çåå¨ï¼æä»¥è¯¥ i å¿
ä¸å¯è½å°äº1 |
| | | // cellMerge å½åè¡å段å并注解 |
| | | boolean merge = isMerge(currentRowObj, rows.get(i - 1), cellMerge); |
| | | |
| | | // æ¯å¦æ·»å å°ç»æé |
| | | boolean isAddResult = false; |
| | | // ææ°è¡ |
| | | int lastRow = i + rowIndex - 1; |
| | | |
| | | // 妿å½åè¡å段å¼åç¼åä¸çåæ®µå¼ä¸ç¸çï¼æä¸æ»¡è¶³åå¹¶æ¡ä»¶ï¼åæ¿æ¢ |
| | | if (!currentRowObjFieldVal.equals(cellValue) || !merge) { |
| | | rowRepeatCellMap.put(field, RepeatCell.of(currentRowObjFieldVal, i)); |
| | | isAddResult = true; |
| | | } |
| | | |
| | | // 妿æåä¸è¡ä¸è½åå¹¶ï¼æ£æ¥ä¹åçæ°æ®æ¯å¦éè¦åå¹¶ï¼å¦ææåä¸è¡å¯ä»¥åå¹¶ï¼åç´æ¥åå¹¶å°æå |
| | | if (i == rows.size() - 1) { |
| | | isAddResult = true; |
| | | if (i > current) { |
| | | lastRow = i + rowIndex; |
| | | } |
| | | } |
| | | |
| | | if (isAddResult && i > current) { |
| | | //妿æ¯åä¸è¡ï¼åè·³è¿åå¹¶ |
| | | if (current + rowIndex == lastRow) { |
| | | continue; |
| | | } |
| | | result.add(new CellRangeAddress(current + rowIndex, lastRow, colNum, colNum)); |
| | | } |
| | | } |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * è·å带æå并注解çåæ®µåç´¢å¼åå并注解信æ¯Mapé |
| | | */ |
| | | private Map<Field, FieldColumnIndex> getFieldColumnIndexMap(Class<?> clazz) { |
| | | boolean annotationPresent = clazz.isAnnotationPresent(ExcelIgnoreUnannotated.class); |
| | | Field[] fields = ReflectUtils.getFields(clazz, field -> { |
| | | if ("serialVersionUID".equals(field.getName())) { |
| | | return false; |
| | | } |
| | | if (field.isAnnotationPresent(ExcelIgnore.class)) { |
| | | return false; |
| | | } |
| | | return !annotationPresent || field.isAnnotationPresent(ExcelProperty.class); |
| | | }); |
| | | |
| | | // ææ³¨è§£çåæ®µ |
| | | Map<Field, FieldColumnIndex> mergeFields = new HashMap<>(); |
| | | for (int i = 0; i < fields.length; i++) { |
| | | Field field = fields[i]; |
| | | if (!field.isAnnotationPresent(CellMerge.class)) { |
| | | continue; |
| | | } |
| | | CellMerge cm = field.getAnnotation(CellMerge.class); |
| | | int index = cm.index() == -1 ? i : cm.index(); |
| | | mergeFields.put(field, FieldColumnIndex.of(index, cm)); |
| | | |
| | | if (hasTitle) { |
| | | ExcelProperty property = field.getAnnotation(ExcelProperty.class); |
| | | rowIndex = Math.max(rowIndex, property.value().length); |
| | | } |
| | | } |
| | | return mergeFields; |
| | | } |
| | | |
| | | private boolean isMerge(Object currentRow, Object preRow, CellMerge cellMerge) { |
| | | final String[] mergeBy = cellMerge.mergeBy(); |
| | | if (StrUtil.isAllNotBlank(mergeBy)) { |
| | | // æ¯å¯¹å½åè¡åä¸ä¸è¡çåä¸ªå±æ§å¼ä¸ä¸æ¯å¯¹ 妿å
¨ä¸ºç å为ç |
| | | for (String fieldName : mergeBy) { |
| | | final Object valCurrent = ReflectUtil.getFieldValue(currentRow, fieldName); |
| | | final Object valPre = ReflectUtil.getFieldValue(preRow, fieldName); |
| | | if (!Objects.equals(valPre, valCurrent)) { |
| | | // ä¾èµåæ®µå¦æä»»ä¸ä¸çå¼,åæ è®°ä¸ºä¸å¯åå¹¶ |
| | | return false; |
| | | } |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * åå
æ ¼åå¹¶ |
| | | */ |
| | | record RepeatCell(Object value, int current) { |
| | | static RepeatCell of(Object value, int current) { |
| | | return new RepeatCell(value, current); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * åæ®µåç´¢å¼ååå¹¶æ³¨è§£ä¿¡æ¯ |
| | | */ |
| | | record FieldColumnIndex(int colIndex, CellMerge cellMerge) { |
| | | static FieldColumnIndex of(int colIndex, CellMerge cellMerge) { |
| | | return new FieldColumnIndex(colIndex, cellMerge); |
| | | } |
| | | } |
| | | /** |
| | | * å建ä¸ä¸ªåå
æ ¼åå¹¶å¤çå¨å®ä¾ |
| | | * |
| | | * @param hasTitle æ¯å¦åå¹¶æ é¢ |
| | | * @param rowIndex è¡ç´¢å¼ |
| | | * @return åå
æ ¼åå¹¶å¤çå¨ |
| | | */ |
| | | public static CellMergeHandler of(final boolean hasTitle, final int rowIndex) { |
| | | return new CellMergeHandler(hasTitle, rowIndex); |
| | | } |
| | | |
| | | /** |
| | | * å建ä¸ä¸ªåå
æ ¼åå¹¶å¤çå¨å®ä¾ |
| | | * |
| | | * @param hasTitle æ¯å¦åå¹¶æ é¢ |
| | | * @return åå
æ ¼åå¹¶å¤çå¨ |
| | | */ |
| | | public static CellMergeHandler of(final boolean hasTitle) { |
| | | return new CellMergeHandler(hasTitle); |
| | | } |
| | | |
| | | /** |
| | | * å建ä¸ä¸ªåå
æ ¼åå¹¶å¤çå¨å®ä¾ï¼é»è®¤ä¸åå¹¶æ é¢ï¼ |
| | | * |
| | | * @return åå
æ ¼åå¹¶å¤çå¨ |
| | | */ |
| | | public static CellMergeHandler of() { |
| | | return new CellMergeHandler(false); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.core; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.idev.excel.metadata.Head; |
| | | import cn.idev.excel.write.handler.SheetWriteHandler; |
| | | import cn.idev.excel.write.merge.AbstractMergeStrategy; |
| | | import cn.idev.excel.write.metadata.holder.WriteSheetHolder; |
| | | import cn.idev.excel.write.metadata.holder.WriteWorkbookHolder; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.poi.ss.usermodel.Cell; |
| | | import org.apache.poi.ss.usermodel.Sheet; |
| | | import org.apache.poi.ss.util.CellRangeAddress; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * åå¼éå¤åå¹¶çç¥ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Slf4j |
| | | public class CellMergeStrategy extends AbstractMergeStrategy implements SheetWriteHandler { |
| | | |
| | | private final List<CellRangeAddress> cellList; |
| | | |
| | | public CellMergeStrategy(List<CellRangeAddress> cellList) { |
| | | this.cellList = cellList; |
| | | } |
| | | |
| | | public CellMergeStrategy(List<?> list, boolean hasTitle) { |
| | | this.cellList = CellMergeHandler.of(hasTitle).handle(list); |
| | | } |
| | | |
| | | public CellMergeStrategy(List<?> list, boolean hasTitle, int rowIndex) { |
| | | this.cellList = CellMergeHandler.of(hasTitle, rowIndex).handle(list); |
| | | } |
| | | |
| | | @Override |
| | | protected void merge(Sheet sheet, Cell cell, Head head, Integer relativeRowIndex) { |
| | | if (CollUtil.isEmpty(cellList)) { |
| | | return; |
| | | } |
| | | // åå
æ ¼åå
¥äº,éååå¹¶åºå,å¦æè¯¥Cellå¨åºåå
,ä½éé¦è¡,忏
空 |
| | | final int rowIndex = cell.getRowIndex(); |
| | | for (CellRangeAddress cellAddresses : cellList) { |
| | | final int firstRow = cellAddresses.getFirstRow(); |
| | | if (cellAddresses.isInRange(cell) && rowIndex != firstRow) { |
| | | cell.setBlank(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void afterSheetCreate(final WriteWorkbookHolder writeWorkbookHolder, final WriteSheetHolder writeSheetHolder) { |
| | | if (CollUtil.isEmpty(cellList)) { |
| | | return; |
| | | } |
| | | // å¨ Sheet åå»ºæ¶æååå
¥åå¹¶åºåï¼åç»åå
¥åªä¼å½±å馿 ¼ï¼ä¸ä¼ç§»é¤åå¹¶ |
| | | final Sheet sheet = writeSheetHolder.getSheet(); |
| | | for (CellRangeAddress item : cellList) { |
| | | sheet.addMergedRegion(item); |
| | | } |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.core; |
| | | |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.idev.excel.context.AnalysisContext; |
| | | import cn.idev.excel.event.AnalysisEventListener; |
| | | import cn.idev.excel.exception.ExcelAnalysisException; |
| | | import cn.idev.excel.exception.ExcelDataConvertException; |
| | | import org.dromara.common.core.utils.StreamUtils; |
| | | import org.dromara.common.core.utils.ValidatorUtils; |
| | | import org.dromara.common.json.utils.JsonUtils; |
| | | import jakarta.validation.ConstraintViolation; |
| | | import jakarta.validation.ConstraintViolationException; |
| | | import lombok.NoArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * Excel 导å
¥çå¬ |
| | | * |
| | | * @author Yjoioooo |
| | | * @author Lion Li |
| | | */ |
| | | @Slf4j |
| | | @NoArgsConstructor |
| | | public class DefaultExcelListener<T> extends AnalysisEventListener<T> implements ExcelListener<T> { |
| | | |
| | | /** |
| | | * æ¯å¦Validatoræ£éªï¼é»è®¤ä¸ºæ¯ |
| | | */ |
| | | private Boolean isValidate = Boolean.TRUE; |
| | | |
| | | /** |
| | | * excel è¡¨å¤´æ°æ® |
| | | */ |
| | | private Map<Integer, String> headMap; |
| | | |
| | | /** |
| | | * 导å
¥åæ§ |
| | | */ |
| | | private ExcelResult<T> excelResult; |
| | | |
| | | public DefaultExcelListener(boolean isValidate) { |
| | | this.excelResult = new DefaultExcelResult<>(); |
| | | this.isValidate = isValidate; |
| | | } |
| | | |
| | | /** |
| | | * å¤çå¼å¸¸ |
| | | * |
| | | * @param exception ExcelDataConvertException |
| | | * @param context Excel ä¸ä¸æ |
| | | */ |
| | | @Override |
| | | public void onException(Exception exception, AnalysisContext context) throws Exception { |
| | | String errMsg = null; |
| | | if (exception instanceof ExcelDataConvertException excelDataConvertException) { |
| | | // å¦ææ¯æä¸ä¸ªåå
æ ¼ç转æ¢å¼å¸¸ è½è·åå°å
·ä½è¡å· |
| | | Integer rowIndex = excelDataConvertException.getRowIndex(); |
| | | Integer columnIndex = excelDataConvertException.getColumnIndex(); |
| | | errMsg = StrUtil.format("第{}è¡-第{}å-表头{}: è§£æå¼å¸¸<br/>", |
| | | rowIndex + 1, columnIndex + 1, headMap.get(columnIndex)); |
| | | if (log.isDebugEnabled()) { |
| | | log.error(errMsg); |
| | | } |
| | | } |
| | | if (exception instanceof ConstraintViolationException constraintViolationException) { |
| | | Set<ConstraintViolation<?>> constraintViolations = constraintViolationException.getConstraintViolations(); |
| | | String constraintViolationsMsg = StreamUtils.join(constraintViolations, ConstraintViolation::getMessage, ", "); |
| | | errMsg = StrUtil.format("第{}è¡æ°æ®æ ¡éªå¼å¸¸: {}", context.readRowHolder().getRowIndex() + 1, constraintViolationsMsg); |
| | | if (log.isDebugEnabled()) { |
| | | log.error(errMsg); |
| | | } |
| | | } |
| | | excelResult.getErrorList().add(errMsg); |
| | | throw new ExcelAnalysisException(errMsg); |
| | | } |
| | | |
| | | @Override |
| | | public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) { |
| | | this.headMap = headMap; |
| | | log.debug("è§£æå°ä¸æ¡è¡¨å¤´æ°æ®: {}", JsonUtils.toJsonString(headMap)); |
| | | } |
| | | |
| | | @Override |
| | | public void invoke(T data, AnalysisContext context) { |
| | | if (isValidate) { |
| | | ValidatorUtils.validate(data); |
| | | } |
| | | excelResult.getList().add(data); |
| | | } |
| | | |
| | | @Override |
| | | public void doAfterAllAnalysed(AnalysisContext context) { |
| | | log.debug("æææ°æ®è§£æå®æï¼"); |
| | | } |
| | | |
| | | @Override |
| | | public ExcelResult<T> getExcelResult() { |
| | | return excelResult; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.core; |
| | | |
| | | import cn.hutool.core.util.StrUtil; |
| | | import lombok.Setter; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * é»è®¤excelè¿å对象 |
| | | * |
| | | * @author Yjoioooo |
| | | * @author Lion Li |
| | | */ |
| | | public class DefaultExcelResult<T> implements ExcelResult<T> { |
| | | |
| | | /** |
| | | * æ°æ®å¯¹è±¡list |
| | | */ |
| | | @Setter |
| | | private List<T> list; |
| | | |
| | | /** |
| | | * é误信æ¯å表 |
| | | */ |
| | | @Setter |
| | | private List<String> errorList; |
| | | |
| | | public DefaultExcelResult() { |
| | | this.list = new ArrayList<>(); |
| | | this.errorList = new ArrayList<>(); |
| | | } |
| | | |
| | | public DefaultExcelResult(List<T> list, List<String> errorList) { |
| | | this.list = list; |
| | | this.errorList = errorList; |
| | | } |
| | | |
| | | public DefaultExcelResult(ExcelResult<T> excelResult) { |
| | | this.list = excelResult.getList(); |
| | | this.errorList = excelResult.getErrorList(); |
| | | } |
| | | |
| | | @Override |
| | | public List<T> getList() { |
| | | return list; |
| | | } |
| | | |
| | | @Override |
| | | public List<String> getErrorList() { |
| | | return errorList; |
| | | } |
| | | |
| | | /** |
| | | * è·å导å
¥åæ§ |
| | | * |
| | | * @return 导å
¥åæ§ |
| | | */ |
| | | @Override |
| | | public String getAnalysis() { |
| | | int successCount = list.size(); |
| | | int errorCount = errorList.size(); |
| | | if (successCount == 0) { |
| | | return "读åå¤±è´¥ï¼æªè§£æå°æ°æ®"; |
| | | } else { |
| | | if (errorCount == 0) { |
| | | return StrUtil.format("æåæ¨ï¼å
¨é¨è¯»åæåï¼å
±{}æ¡", successCount); |
| | | } else { |
| | | return ""; |
| | | } |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.core; |
| | | |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.function.Function; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * <h1>Excel䏿å¯é项</h1> |
| | | * 注æï¼ä¸ºç¡®ä¿ä¸ææ¡è§£ææ£ç¡®ï¼ä¼ å¼å¡å¿
使ç¨createOptionValue()å为å¼çæ¼æ¥ |
| | | * |
| | | * @author Emil.Zhang |
| | | */ |
| | | @Data |
| | | @AllArgsConstructor |
| | | @NoArgsConstructor |
| | | @SuppressWarnings("unused") |
| | | public class DropDownOptions { |
| | | /** |
| | | * ä¸çº§ä¸ææå¨åindexï¼ä»0å¼å§ç® |
| | | */ |
| | | private int index = 0; |
| | | /** |
| | | * äºçº§ä¸ææå¨çindexï¼ä»0å¼å§ç®ï¼ä¸è½ä¸ä¸çº§ç¸å |
| | | */ |
| | | private int nextIndex = 0; |
| | | /** |
| | | * ä¸çº§ä¸ææå
å«çæ°æ® |
| | | */ |
| | | private List<String> options = new ArrayList<>(); |
| | | /** |
| | | * äºçº§ä¸ææå
å«çæ°æ®Map |
| | | * <p>以æ¯ä¸ä¸ªä¸çº§é项å¼ä¸ºKeyï¼æ¯ä¸ªä¸çº§é项对åºçäºçº§æ°æ®ä¸ºValue</p> |
| | | */ |
| | | private Map<String, List<String>> nextOptions = new HashMap<>(); |
| | | /** |
| | | * åé符 |
| | | */ |
| | | private static final String DELIMITER = "_"; |
| | | |
| | | /** |
| | | * åå»ºåªæä¸çº§ç䏿é |
| | | */ |
| | | public DropDownOptions(int index, List<String> options) { |
| | | this.index = index; |
| | | this.options = options; |
| | | } |
| | | |
| | | /** |
| | | * <h2>å建æ¯ä¸ªé项å¯éå¼</h2> |
| | | * <p>注æï¼ä¸è½ä»¥æ°åï¼ç¹æ®ç¬¦å·å¼å¤´ï¼é项ä¸ä¸å¯ä»¥å
å«ä»»ä½è¿ç®ç¬¦å·</p> |
| | | * |
| | | * @param vars å¯éå¼å
å
å«çåæ° |
| | | * @return åè§çå¯éå¼ |
| | | */ |
| | | public static String createOptionValue(Object... vars) { |
| | | StringBuilder stringBuffer = new StringBuilder(); |
| | | String regex = "^[\\S\\d\\u4e00-\\u9fa5]+$"; |
| | | for (int i = 0; i < vars.length; i++) { |
| | | String var = StrUtil.trimToEmpty(Convert.toStr(vars[i])); |
| | | if (!var.matches(regex)) { |
| | | throw new ServiceException("éé¡¹æ°æ®ä¸ç¬¦åè§åï¼ä»
å
许使ç¨ä¸è±æåç¬¦ä»¥åæ°å"); |
| | | } |
| | | stringBuffer.append(var); |
| | | if (i < vars.length - 1) { |
| | | // ç´è³æåä¸ä¸ªåï¼é½ä»¥_ä½ä¸ºåå²çº¿ |
| | | stringBuffer.append(DELIMITER); |
| | | } |
| | | } |
| | | if (stringBuffer.toString().matches("^\\d_*$")) { |
| | | throw new ServiceException("ç¦æ¢ä»¥æ°åå¼å¤´"); |
| | | } |
| | | return stringBuffer.toString(); |
| | | } |
| | | |
| | | /** |
| | | * å°å¤çååççå¯éå¼è§£æä¸ºåå§çåæ° |
| | | * |
| | | * @param option ç»è¿å¤çåçåççå¯é项 |
| | | * @return åå§çåæ° |
| | | */ |
| | | public static List<String> analyzeOptionValue(String option) { |
| | | return StrUtil.split(option, DELIMITER, true, true); |
| | | } |
| | | |
| | | /** |
| | | * å建级è䏿é项 |
| | | * |
| | | * @param parentList ç¶å®ä½å¯é项åå§æ°æ® |
| | | * @param parentIndex ç¶ä¸æéä½ç½® |
| | | * @param sonList åå®ä½å¯é项åå§æ°æ® |
| | | * @param sonIndex å䏿éä½ç½® |
| | | * @param parentHowToGetIdFunction ç¶ç±»å¦ä½è·åå¯ä¸æ è¯ |
| | | * @param sonHowToGetParentIdFunction åç±»å¦ä½è·åç¶ç±»çå¯ä¸æ è¯ |
| | | * @param howToBuildEveryOption å¦ä½çæä¸æéå
容 |
| | | * @return 级è䏿é项 |
| | | */ |
| | | public static <T> DropDownOptions buildLinkedOptions(List<T> parentList, |
| | | int parentIndex, |
| | | List<T> sonList, |
| | | int sonIndex, |
| | | Function<T, Number> parentHowToGetIdFunction, |
| | | Function<T, Number> sonHowToGetParentIdFunction, |
| | | Function<T, String> howToBuildEveryOption) { |
| | | DropDownOptions parentLinkSonOptions = new DropDownOptions(); |
| | | // å
å建ç¶ç±»ç䏿 |
| | | parentLinkSonOptions.setIndex(parentIndex); |
| | | parentLinkSonOptions.setOptions( |
| | | parentList.stream() |
| | | .map(howToBuildEveryOption) |
| | | .collect(Collectors.toList()) |
| | | ); |
| | | // æåç¶-å级è䏿 |
| | | Map<String, List<String>> sonOptions = new HashMap<>(); |
| | | // ç¶çº§ä¾æ®èªå·±çIDåç» |
| | | Map<Number, List<T>> parentGroupByIdMap = |
| | | parentList.stream().collect(Collectors.groupingBy(parentHowToGetIdFunction)); |
| | | // éåæ¯ä¸ªåéï¼æåå°Mapä¸ |
| | | sonList.forEach(everySon -> { |
| | | if (parentGroupByIdMap.containsKey(sonHowToGetParentIdFunction.apply(everySon))) { |
| | | // æ¾å°å¯¹åºçä¸çº§ |
| | | T parentObj = parentGroupByIdMap.get(sonHowToGetParentIdFunction.apply(everySon)).get(0); |
| | | // æååç§°åIDä½ä¸ºKey |
| | | String key = howToBuildEveryOption.apply(parentObj); |
| | | // Key对åºçValue |
| | | List<String> thisParentSonOptionList; |
| | | if (sonOptions.containsKey(key)) { |
| | | thisParentSonOptionList = sonOptions.get(key); |
| | | } else { |
| | | thisParentSonOptionList = new ArrayList<>(); |
| | | sonOptions.put(key, thisParentSonOptionList); |
| | | } |
| | | // å¾Value䏿·»å å½ååéé项 |
| | | thisParentSonOptionList.add(howToBuildEveryOption.apply(everySon)); |
| | | } |
| | | }); |
| | | parentLinkSonOptions.setNextIndex(sonIndex); |
| | | parentLinkSonOptions.setNextOptions(sonOptions); |
| | | return parentLinkSonOptions; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.core; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.util.ArrayUtil; |
| | | import cn.hutool.core.util.EnumUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.idev.excel.metadata.FieldCache; |
| | | import cn.idev.excel.metadata.FieldWrapper; |
| | | import cn.idev.excel.util.ClassUtils; |
| | | import cn.idev.excel.write.handler.SheetWriteHandler; |
| | | import cn.idev.excel.write.metadata.holder.WriteSheetHolder; |
| | | import cn.idev.excel.write.metadata.holder.WriteWorkbookHolder; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.poi.ss.usermodel.*; |
| | | import org.apache.poi.ss.util.CellRangeAddressList; |
| | | import org.apache.poi.ss.util.WorkbookUtil; |
| | | import org.apache.poi.xssf.usermodel.XSSFDataValidation; |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | import org.dromara.common.core.service.DictService; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.dromara.common.core.utils.StreamUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.excel.annotation.ExcelDictFormat; |
| | | import org.dromara.common.excel.annotation.ExcelDynamicOptions; |
| | | import org.dromara.common.excel.annotation.ExcelEnumFormat; |
| | | |
| | | import java.lang.reflect.Field; |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * <h1>Excelè¡¨æ ¼ä¸æéæä½</h1> |
| | | * èèå°ä¸æéè¿å¤å¯è½å¯¼è´Excelæå¼ç¼æ
¢çé®é¢ï¼åªæ ¡éªå1000è¡ |
| | | * <p> |
| | | * å³åªæå1000è¡çæ°æ®å¯ä»¥ç¨ä¸ææ¡ï¼è¶
åºçèªè¡éè¿éå¶æ°æ®éçå½¢å¼ï¼ç¬¬äºæ¬¡è¾åº |
| | | * |
| | | * @author Emil.Zhang |
| | | */ |
| | | @Slf4j |
| | | public class ExcelDownHandler implements SheetWriteHandler { |
| | | |
| | | /** |
| | | * Excelè¡¨æ ¼ä¸çååè±æ |
| | | * ä»
为äºè§£æåè±æï¼ç¦æ¢ä¿®æ¹ |
| | | */ |
| | | private static final String EXCEL_COLUMN_NAME = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
| | | /** |
| | | * åéæ°æ®Sheetå |
| | | */ |
| | | private static final String OPTIONS_SHEET_NAME = "options"; |
| | | /** |
| | | * èå¨éæ©æ°æ®Sheetåç头 |
| | | */ |
| | | private static final String LINKED_OPTIONS_SHEET_NAME = "linkedOptions"; |
| | | /** |
| | | * 䏿å¯é项 |
| | | */ |
| | | private final List<DropDownOptions> dropDownOptions; |
| | | private final DictService dictService; |
| | | /** |
| | | * å½ååéè¿åº¦ |
| | | */ |
| | | private int currentOptionsColumnIndex; |
| | | /** |
| | | * å½åèå¨éæ©è¿åº¦ |
| | | */ |
| | | private int currentLinkedOptionsSheetIndex; |
| | | |
| | | public ExcelDownHandler(List<DropDownOptions> options) { |
| | | this.dropDownOptions = options; |
| | | this.currentOptionsColumnIndex = 0; |
| | | this.currentLinkedOptionsSheetIndex = 0; |
| | | this.dictService = SpringUtils.getBean(DictService.class); |
| | | } |
| | | |
| | | /** |
| | | * <h2>å¼å§åå»ºä¸ææ°æ®</h2> |
| | | * 1.éè¿è§£æä¼ å
¥ç@ExcelPropertyå级æ¯å¦æ 注æ@DropDowné项 |
| | | * 妿æä¸è®¾ç½®äºvalueå¼ï¼åå°å
¶ç´æ¥ç½®ä¸ºä¸æå¯é项 |
| | | * <p> |
| | | * 2.æè
å¨è°ç¨ExcelUtilæ¶æå®äºå¯é项ï¼å°ä¾æ®ä¼ å
¥çå¯é项å䏿 |
| | | * <p> |
| | | * 3.äºè
å¹¶åï¼æ³¨æè°ç¨æ¹å¼ |
| | | */ |
| | | @Override |
| | | public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { |
| | | Sheet sheet = writeSheetHolder.getSheet(); |
| | | // å¼å§è®¾ç½®ä¸ææ¡ HSSFWorkbook |
| | | DataValidationHelper helper = sheet.getDataValidationHelper(); |
| | | Workbook workbook = writeWorkbookHolder.getWorkbook(); |
| | | FieldCache fieldCache = ClassUtils.declaredFields(writeWorkbookHolder.getClazz(), writeWorkbookHolder); |
| | | for (Map.Entry<Integer, FieldWrapper> entry : fieldCache.getSortedFieldMap().entrySet()) { |
| | | Integer index = entry.getKey(); |
| | | FieldWrapper wrapper = entry.getValue(); |
| | | Field field = wrapper.getField(); |
| | | // 循ç¯å®ä½ä¸çæ¯ä¸ªå±æ§ |
| | | // å¯éçä¸æå¼ |
| | | List<String> options = new ArrayList<>(); |
| | | if (field.isAnnotationPresent(ExcelDictFormat.class)) { |
| | | // 妿æå®äº@ExcelDictFormatï¼å使ç¨åå
¸çé»è¾ |
| | | ExcelDictFormat format = field.getDeclaredAnnotation(ExcelDictFormat.class); |
| | | String dictType = format.dictType(); |
| | | String converterExp = format.readConverterExp(); |
| | | if (StringUtils.isNotBlank(dictType)) { |
| | | // å¦æä¼ éäºåå
¸åï¼å便®åå
¸å»ºç«ä¸æ |
| | | Collection<String> values = Optional.ofNullable(dictService.getAllDictByDictType(dictType)) |
| | | .orElseThrow(() -> new ServiceException("åå
¸ {} ä¸åå¨", dictType)) |
| | | .values(); |
| | | options = new ArrayList<>(values); |
| | | } else if (StringUtils.isNotBlank(converterExp)) { |
| | | // 妿æå®äºç¡®åçå¼ï¼åç´æ¥è§£æç¡®åçå¼ |
| | | List<String> strList = StringUtils.splitList(converterExp, format.separator()); |
| | | options = StreamUtils.toList(strList, s -> StringUtils.split(s, "=")[1]); |
| | | } |
| | | } else if (field.isAnnotationPresent(ExcelEnumFormat.class)) { |
| | | // å¦å妿æå®äº@ExcelEnumFormatï¼åä½¿ç¨æä¸¾çé»è¾ |
| | | ExcelEnumFormat format = field.getDeclaredAnnotation(ExcelEnumFormat.class); |
| | | List<Object> values = EnumUtil.getFieldValues(format.enumClass(), format.textField()); |
| | | options = StreamUtils.toList(values, Convert::toStr); |
| | | } else if (field.isAnnotationPresent(ExcelDynamicOptions.class)) { |
| | | // å¤ç卿䏿é项 |
| | | ExcelDynamicOptions dynamicOptions = field.getDeclaredAnnotation(ExcelDynamicOptions.class); |
| | | // è·åæä¾è
å®ä¾ |
| | | ExcelOptionsProvider provider = SpringUtils.getBean(dynamicOptions.providerClass()); |
| | | Set<String> providerOptions = provider.getOptions(); |
| | | if (CollUtil.isNotEmpty(providerOptions)) { |
| | | options = new ArrayList<>(providerOptions); |
| | | } |
| | | } |
| | | if (ObjectUtil.isNotEmpty(options)) { |
| | | // ä»
å½ä¸æå¯é项ä¸ä¸ºç©ºæ¶æ§è¡ |
| | | if (options.size() > 20) { |
| | | // è¿ééå¶å¦æå¯é项大äº20ï¼å使ç¨é¢å¤è¡¨å½¢å¼ |
| | | dropDownWithSheet(helper, workbook, sheet, index, options); |
| | | } else { |
| | | // å¦å使ç¨åºå®å¼å½¢å¼ |
| | | dropDownWithSimple(helper, sheet, index, options); |
| | | } |
| | | } |
| | | } |
| | | if (CollUtil.isEmpty(dropDownOptions)) { |
| | | return; |
| | | } |
| | | dropDownOptions.forEach(everyOptions -> { |
| | | // å¦æä¼ éäºä¸ææ¡éæ©å¨åæ° |
| | | if (!everyOptions.getNextOptions().isEmpty()) { |
| | | // å½äºçº§é项ä¸ä¸ºç©ºæ¶ï¼ä½¿ç¨é¢å¤å
³è表çå½¢å¼ |
| | | dropDownLinkedOptions(helper, workbook, sheet, everyOptions); |
| | | } else if (everyOptions.getOptions().size() > 10) { |
| | | // å½ä¸çº§éé¡¹åæ°ä¸ªæ°å¤§äº10ï¼ä½¿ç¨é¢å¤è¡¨çå½¢å¼ |
| | | dropDownWithSheet(helper, workbook, sheet, everyOptions.getIndex(), everyOptions.getOptions()); |
| | | } else { |
| | | // å¦å使ç¨é»è®¤å½¢å¼ |
| | | dropDownWithSimple(helper, sheet, everyOptions.getIndex(), everyOptions.getOptions()); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | /** |
| | | * <h2>ç®å䏿æ¡</h2> |
| | | * ç´æ¥å°å¯éé¡¹æ¼æ¥ä¸ºæå®åçæ°æ®æ ¡éªå¼ |
| | | * |
| | | * @param celIndex åindex |
| | | * @param value 䏿éå¯éå¼ |
| | | */ |
| | | private void dropDownWithSimple(DataValidationHelper helper, Sheet sheet, Integer celIndex, List<String> value) { |
| | | if (ObjectUtil.isEmpty(value)) { |
| | | return; |
| | | } |
| | | this.markOptionsToSheet(helper, sheet, celIndex, helper.createExplicitListConstraint(ArrayUtil.toArray(value, String.class))); |
| | | } |
| | | |
| | | /** |
| | | * <h2>é¢å¤è¡¨æ ¼å½¢å¼ç级è䏿æ¡</h2> |
| | | * |
| | | * @param options é¢å¤è¡¨æ ¼å½¢å¼åå¨ç䏿å¯é项 |
| | | */ |
| | | private void dropDownLinkedOptions(DataValidationHelper helper, Workbook workbook, Sheet sheet, DropDownOptions options) { |
| | | String linkedOptionsSheetName = String.format("%s_%d", LINKED_OPTIONS_SHEET_NAME, currentLinkedOptionsSheetIndex); |
| | | // å建èå¨ä¸ææ°æ®è¡¨ |
| | | Sheet linkedOptionsDataSheet = workbook.createSheet(WorkbookUtil.createSafeSheetName(linkedOptionsSheetName)); |
| | | // å°ä¸æè¡¨éè |
| | | workbook.setSheetHidden(workbook.getSheetIndex(linkedOptionsDataSheet), true); |
| | | // éé¡¹æ°æ® |
| | | List<String> firstOptions = options.getOptions(); |
| | | Map<String, List<String>> secoundOptionsMap = options.getNextOptions(); |
| | | |
| | | // éç¨æè¡å¡«å
æ°æ®çæ¹å¼ï¼é¿å
åºç°æ°æ®æ æ³åå
¥çé®é¢ |
| | | // Attempting to write a row in the range that is already written to disk |
| | | |
| | | // 使ç¨ArrayListè®°è½½æ°æ®ï¼é²æ¢ä¹±åº |
| | | List<String> columnNames = new ArrayList<>(); |
| | | // åå
¥ç¬¬ä¸è¡ï¼å³ç¬¬ä¸çº§çæ°æ® |
| | | Row firstRow = linkedOptionsDataSheet.createRow(0); |
| | | for (int columnIndex = 0; columnIndex < firstOptions.size(); columnIndex++) { |
| | | String columnName = firstOptions.get(columnIndex); |
| | | firstRow.createCell(columnIndex) |
| | | .setCellValue(columnName); |
| | | columnNames.add(columnName); |
| | | } |
| | | |
| | | // å建å称管çå¨ |
| | | Name name = workbook.createName(); |
| | | // 设置å称管çå¨çå«å |
| | | name.setNameName(linkedOptionsSheetName); |
| | | // 以横å第ä¸è¡å建ä¸çº§ä¸ææ¼æ¥å¼ç¨ä½ç½® |
| | | String firstOptionsFunction = String.format("%s!$%s$1:$%s$1", |
| | | linkedOptionsSheetName, |
| | | getExcelColumnName(0), |
| | | getExcelColumnName(firstOptions.size()) |
| | | ); |
| | | // 设置å称管çå¨çå¼ç¨ä½ç½® |
| | | name.setRefersToFormula(firstOptionsFunction); |
| | | // è®¾ç½®æ°æ®æ ¡éªä¸ºåºå模å¼ï¼å¼ç¨çæ¯å称管çå¨ä¸çå«å |
| | | this.markOptionsToSheet(helper, sheet, options.getIndex(), helper.createFormulaListConstraint(linkedOptionsSheetName)); |
| | | |
| | | // å建äºçº§é项çå称管çå¨ |
| | | for (int columIndex = 0; columIndex < columnNames.size(); columIndex++) { |
| | | // åå |
| | | String firstOptionsColumnName = getExcelColumnName(columIndex); |
| | | // 对åºçä¸çº§å¼ |
| | | String thisFirstOptionsValue = columnNames.get(columIndex); |
| | | |
| | | // 以该ä¸çº§é项å¼å建åå称管çå¨ |
| | | Name sonName = workbook.createName(); |
| | | // 设置å称管çå¨çå«å |
| | | sonName.setNameName(thisFirstOptionsValue); |
| | | // 以第äºè¡è¯¥åæ°æ®æ¼æ¥å¼ç¨ä½ç½® |
| | | String sonFunction = String.format("%s!$%s$2:$%s$%d", |
| | | linkedOptionsSheetName, |
| | | firstOptionsColumnName, |
| | | firstOptionsColumnName, |
| | | // äºçº§é项åå¨å设置为(é项个æ°+1)è¡ï¼å¦å设置为2è¡ |
| | | Math.max(Optional.ofNullable(secoundOptionsMap.get(thisFirstOptionsValue)) |
| | | .orElseGet(ArrayList::new).size(), 1) + 1 |
| | | ); |
| | | // 设置å称管çå¨çå¼ç¨ä½ç½® |
| | | sonName.setRefersToFormula(sonFunction); |
| | | // æ°æ®éªè¯ä¸ºåºå模å¼ï¼å¼ç¨å°æ¯ä¸ä¸ªä¸»è¡¨ä¸çäºçº§é项ä½ç½® |
| | | // å建å项çå称管çå¨ï¼åªæ¯ä¸ºäºä½¿å¾Excelå¯ä»¥è¯å«å°æ°æ® |
| | | String mainSheetFirstOptionsColumnName = getExcelColumnName(options.getIndex()); |
| | | for (int i = 0; i < 100; i++) { |
| | | // 以ä¸çº§é项对åºç䏻使å¨ä½ç½®å建äºçº§ä¸æ |
| | | String secondOptionsFunction = String.format("=INDIRECT(%s%d)", mainSheetFirstOptionsColumnName, i + 1); |
| | | // äºçº§åªè½ä¸»è¡¨æ¯ä¸è¡çæ¯ä¸åæ·»å äºçº§æ ¡éª |
| | | markLinkedOptionsToSheet(helper, sheet, i, options.getNextIndex(), helper.createFormulaListConstraint(secondOptionsFunction)); |
| | | } |
| | | } |
| | | |
| | | // å°äºçº§æ°æ®å¤ç为æè¡åºå |
| | | Map<Integer, List<String>> columnValueMap = new HashMap<>(); |
| | | int currentRow = 1; |
| | | while (currentRow >= 0) { |
| | | boolean flag = false; |
| | | List<String> rowData = new ArrayList<>(); |
| | | for (String columnName : columnNames) { |
| | | List<String> data = secoundOptionsMap.get(columnName); |
| | | if (CollUtil.isEmpty(data)) { |
| | | // æ·»å 空å符串填å
ä½ç½® |
| | | rowData.add(" "); |
| | | continue; |
| | | } |
| | | // å第ä¸ä¸ª |
| | | String str = data.get(0); |
| | | rowData.add(str); |
| | | // éè¿ç§»é¤çæ¹å¼é¿å
éå¤ |
| | | data.remove(0); |
| | | // 设置å¯ä»¥ç»§ç» |
| | | flag = true; |
| | | } |
| | | columnValueMap.put(currentRow, rowData); |
| | | // å¯ä»¥ç»§ç»ï¼åå¢å è¡æ°ï¼å¦åç½®ä¸ºè´æ°è·³åºå¾ªç¯ |
| | | if (flag) { |
| | | currentRow++; |
| | | } else { |
| | | currentRow = -1; |
| | | } |
| | | } |
| | | |
| | | // å¡«å
第äºçº§éé¡¹æ°æ® |
| | | columnValueMap.forEach((rowIndex, rowValues) -> { |
| | | Row row = linkedOptionsDataSheet.createRow(rowIndex); |
| | | for (int columnIndex = 0; columnIndex < rowValues.size(); columnIndex++) { |
| | | String rowValue = rowValues.get(columnIndex); |
| | | // å¡«å
ä½ç½®çé¨å䏿¸²æ |
| | | if (StrUtil.isNotBlank(rowValue)) { |
| | | row.createCell(columnIndex) |
| | | .setCellValue(rowValue); |
| | | } |
| | | } |
| | | }); |
| | | |
| | | currentLinkedOptionsSheetIndex++; |
| | | } |
| | | |
| | | /** |
| | | * <h2>é¢å¤è¡¨æ ¼å½¢å¼çæ®é䏿æ¡</h2> |
| | | * ç±äºä¸ææ¡å¯é弿°éè¿å¤ï¼ä¸ºæåExcelæå¼æçï¼ä½¿ç¨é¢å¤è¡¨æ ¼å½¢å¼å䏿 |
| | | * |
| | | * @param celIndex 䏿é |
| | | * @param value 䏿éå¯éå¼ |
| | | */ |
| | | private void dropDownWithSheet(DataValidationHelper helper, Workbook workbook, Sheet sheet, Integer celIndex, List<String> value) { |
| | | //ç±äºpoiçååºç¸å
³é®é¢ï¼è¶
è¿100个ä¼è¢«ä¸´æ¶åè¿ç¡¬çï¼å¯¼è´åç»å
ååå¹¶ä¼åºAttempting to write a row[] in the range [] that is already written to disk |
| | | String tmpOptionsSheetName = OPTIONS_SHEET_NAME + "_" + currentOptionsColumnIndex; |
| | | // åå»ºä¸ææ°æ®è¡¨ |
| | | Sheet simpleDataSheet = Optional.ofNullable(workbook.getSheet(WorkbookUtil.createSafeSheetName(tmpOptionsSheetName))) |
| | | .orElseGet(() -> workbook.createSheet(WorkbookUtil.createSafeSheetName(tmpOptionsSheetName))); |
| | | // å°ä¸æè¡¨éè |
| | | workbook.setSheetHidden(workbook.getSheetIndex(simpleDataSheet), true); |
| | | // å®å纵åçä¸çº§éé¡¹æ°æ®è¡¨ |
| | | for (int i = 0; i < value.size(); i++) { |
| | | int finalI = i; |
| | | // è·åæ¯ä¸é项è¡ï¼å¦ææ²¡æåå建 |
| | | Row row = Optional.ofNullable(simpleDataSheet.getRow(i)) |
| | | .orElseGet(() -> simpleDataSheet.createRow(finalI)); |
| | | // è·åæ¬çº§é项对åºçé项åï¼å¦ææ²¡æåå建ãä¸è¿°éç¨å¤ä¸ªsheet,é»è®¤ç´¢å¼ä¸º1å |
| | | Cell cell = Optional.ofNullable(row.getCell(0)) |
| | | .orElseGet(() -> row.createCell(0)); |
| | | // è®¾ç½®å¼ |
| | | cell.setCellValue(value.get(i)); |
| | | } |
| | | |
| | | // å建å称管çå¨ |
| | | Name name = workbook.createName(); |
| | | // 设置å称管çå¨çå«å |
| | | String nameName = String.format("%s_%d", tmpOptionsSheetName, celIndex); |
| | | name.setNameName(nameName); |
| | | // 以纵å第ä¸åå建ä¸çº§ä¸ææ¼æ¥å¼ç¨ä½ç½® |
| | | String function = String.format("%s!$%s$1:$%s$%d", |
| | | tmpOptionsSheetName, |
| | | getExcelColumnName(0), |
| | | getExcelColumnName(0), |
| | | value.size()); |
| | | // 设置å称管çå¨çå¼ç¨ä½ç½® |
| | | name.setRefersToFormula(function); |
| | | // è®¾ç½®æ°æ®æ ¡éªä¸ºåºå模å¼ï¼å¼ç¨çæ¯å称管çå¨ä¸çå«å |
| | | this.markOptionsToSheet(helper, sheet, celIndex, helper.createFormulaListConstraint(nameName)); |
| | | currentOptionsColumnIndex++; |
| | | } |
| | | |
| | | /** |
| | | * æè½½ä¸æçåï¼ä»
éä¸çº§é项 |
| | | */ |
| | | private void markOptionsToSheet(DataValidationHelper helper, Sheet sheet, Integer celIndex, |
| | | DataValidationConstraint constraint) { |
| | | // è®¾ç½®æ°æ®æææ§å è½½å¨åªä¸ªåå
æ ¼ä¸,åä¸ªåæ°å嫿¯ï¼èµ·å§è¡ãç»æ¢è¡ãèµ·å§åãç»æ¢å |
| | | CellRangeAddressList addressList = new CellRangeAddressList(1, 1000, celIndex, celIndex); |
| | | markDataValidationToSheet(helper, sheet, constraint, addressList); |
| | | } |
| | | |
| | | /** |
| | | * æè½½ä¸æçåï¼ä»
éäºçº§é项 |
| | | */ |
| | | private void markLinkedOptionsToSheet(DataValidationHelper helper, Sheet sheet, Integer rowIndex, |
| | | Integer celIndex, DataValidationConstraint constraint) { |
| | | // è®¾ç½®æ°æ®æææ§å è½½å¨åªä¸ªåå
æ ¼ä¸,åä¸ªåæ°å嫿¯ï¼èµ·å§è¡ãç»æ¢è¡ãèµ·å§åãç»æ¢å |
| | | CellRangeAddressList addressList = new CellRangeAddressList(rowIndex, rowIndex, celIndex, celIndex); |
| | | markDataValidationToSheet(helper, sheet, constraint, addressList); |
| | | } |
| | | |
| | | /** |
| | | * åºç¨æ°æ®æ ¡éª |
| | | */ |
| | | private void markDataValidationToSheet(DataValidationHelper helper, Sheet sheet, |
| | | DataValidationConstraint constraint, CellRangeAddressList addressList) { |
| | | // æ°æ®æææ§å¯¹è±¡ |
| | | DataValidation dataValidation = helper.createValidation(constraint, addressList); |
| | | // å¤çExcelå
¼å®¹æ§é®é¢ |
| | | if (dataValidation instanceof XSSFDataValidation) { |
| | | //æ°æ®æ ¡éª |
| | | dataValidation.setSuppressDropDownArrow(true); |
| | | //é误æç¤º |
| | | dataValidation.setErrorStyle(DataValidation.ErrorStyle.STOP); |
| | | dataValidation.createErrorBox("æç¤º", "æ¤å¼ä¸åå
æ ¼å®ä¹æ°æ®ä¸ä¸è´"); |
| | | dataValidation.setShowErrorBox(true); |
| | | //éå®æç¤º |
| | | dataValidation.createPromptBox("å¡«å说æï¼", "å¡«åå
容åªè½ä¸ºä¸æä¸æ°æ®ï¼å
¶ä»æ°æ®å°å¯¼è´å¯¼å
¥å¤±è´¥"); |
| | | dataValidation.setShowPromptBox(true); |
| | | sheet.addValidationData(dataValidation); |
| | | } else { |
| | | dataValidation.setSuppressDropDownArrow(false); |
| | | } |
| | | sheet.addValidationData(dataValidation); |
| | | } |
| | | |
| | | /** |
| | | * <h2>便®åindexè·åååè±æ</h2> |
| | | * 便®åindex转æ¢ä¸ºExcelä¸çååè±æ |
| | | * <p>ä¾å¦ç¬¬1åï¼index为0ï¼è§£æåºæ¥ä¸ºAå</p> |
| | | * 第27åï¼index为26ï¼è§£æä¸ºAAå |
| | | * <p>第28åï¼index为27ï¼è§£æä¸ºABå</p> |
| | | * |
| | | * @param columnIndex åindex |
| | | * @return åindexæå¨å¾è±æå |
| | | */ |
| | | private String getExcelColumnName(int columnIndex) { |
| | | // 26ä¸å¾ªç¯çæ¬¡æ° |
| | | int columnCircleCount = columnIndex / 26; |
| | | // 26ä¸å¾ªç¯å
çä½ç½® |
| | | int thisCircleColumnIndex = columnIndex % 26; |
| | | // 26ä¸å¾ªç¯ç次æ°å¤§äº0ï¼åè§ä¸ºæ åè³å°ä¸¤ä½ |
| | | String columnPrefix = columnCircleCount == 0 |
| | | ? StrUtil.EMPTY |
| | | : StrUtil.subWithLength(EXCEL_COLUMN_NAME, columnCircleCount - 1, 1); |
| | | // ä»26ä¸å¾ªç¯å
å对åºçæ ä½å |
| | | String columnNext = StrUtil.subWithLength(EXCEL_COLUMN_NAME, thisCircleColumnIndex, 1); |
| | | // å°äºè
æ¼æ¥å³ä¸ºæç»çæ ä½å |
| | | return columnPrefix + columnNext; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.core; |
| | | |
| | | import cn.idev.excel.read.listener.ReadListener; |
| | | |
| | | /** |
| | | * Excel 导å
¥çå¬ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public interface ExcelListener<T> extends ReadListener<T> { |
| | | |
| | | ExcelResult<T> getExcelResult(); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.core; |
| | | |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * Excel䏿éé¡¹æ°æ®æä¾æ¥å£ |
| | | * |
| | | * @author Angus |
| | | */ |
| | | public interface ExcelOptionsProvider { |
| | | |
| | | /** |
| | | * è·å䏿éé¡¹æ°æ® |
| | | * |
| | | * @return 䏿é项å表 |
| | | */ |
| | | Set<String> getOptions(); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.core; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * excelè¿å对象 |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | public interface ExcelResult<T> { |
| | | |
| | | /** |
| | | * 对象å表 |
| | | */ |
| | | List<T> getList(); |
| | | |
| | | /** |
| | | * é误å表 |
| | | */ |
| | | List<String> getErrorList(); |
| | | |
| | | /** |
| | | * 导å
¥åæ§ |
| | | */ |
| | | String getAnalysis(); |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.handler; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.idev.excel.annotation.ExcelProperty; |
| | | import cn.idev.excel.metadata.data.DataFormatData; |
| | | import cn.idev.excel.metadata.data.WriteCellData; |
| | | import cn.idev.excel.util.StyleUtil; |
| | | import cn.idev.excel.write.handler.CellWriteHandler; |
| | | import cn.idev.excel.write.handler.SheetWriteHandler; |
| | | import cn.idev.excel.write.handler.context.CellWriteHandlerContext; |
| | | import cn.idev.excel.write.metadata.holder.WriteSheetHolder; |
| | | import cn.idev.excel.write.metadata.style.WriteCellStyle; |
| | | import cn.idev.excel.write.metadata.style.WriteFont; |
| | | import org.apache.poi.ss.usermodel.*; |
| | | import org.apache.poi.xssf.usermodel.XSSFClientAnchor; |
| | | import org.apache.poi.xssf.usermodel.XSSFRichTextString; |
| | | import org.dromara.common.excel.annotation.ExcelNotation; |
| | | import org.dromara.common.excel.annotation.ExcelRequired; |
| | | |
| | | import java.lang.reflect.Field; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * æ¹æ³¨ãå¿
å¡« |
| | | * |
| | | * @author guzhouyanyu |
| | | */ |
| | | public class DataWriteHandler implements SheetWriteHandler, CellWriteHandler { |
| | | |
| | | /** |
| | | * æ¹æ³¨ |
| | | */ |
| | | private final Map<String, String> notationMap; |
| | | |
| | | /** |
| | | * 头ååä½é¢è² |
| | | */ |
| | | private final Map<String, Short> headColumnMap; |
| | | |
| | | |
| | | public DataWriteHandler(Class<?> clazz) { |
| | | notationMap = getNotationMap(clazz); |
| | | headColumnMap = getRequiredMap(clazz); |
| | | } |
| | | |
| | | @Override |
| | | public void afterCellDispose(CellWriteHandlerContext context) { |
| | | if (CollUtil.isEmpty(notationMap) && CollUtil.isEmpty(headColumnMap)) { |
| | | return; |
| | | } |
| | | // 第ä¸è¡ |
| | | WriteCellData<?> cellData = context.getFirstCellData(); |
| | | // 第ä¸ä¸ªæ ¼å |
| | | WriteCellStyle writeCellStyle = cellData.getOrCreateStyle(); |
| | | |
| | | if (context.getHead()) { |
| | | DataFormatData dataFormatData = new DataFormatData(); |
| | | // åå
æ ¼è®¾ç½®ä¸ºææ¬æ ¼å¼ |
| | | dataFormatData.setIndex((short) 49); |
| | | writeCellStyle.setDataFormatData(dataFormatData); |
| | | Cell cell = context.getCell(); |
| | | WriteSheetHolder writeSheetHolder = context.getWriteSheetHolder(); |
| | | Sheet sheet = writeSheetHolder.getSheet(); |
| | | Workbook workbook = writeSheetHolder.getSheet().getWorkbook(); |
| | | Drawing<?> drawing = sheet.createDrawingPatriarch(); |
| | | // 设置æ é¢å使 ·å¼ |
| | | WriteFont headWriteFont = new WriteFont(); |
| | | // å ç² |
| | | headWriteFont.setBold(true); |
| | | if (CollUtil.isNotEmpty(headColumnMap) && headColumnMap.containsKey(cell.getStringCellValue())) { |
| | | // 设置åä½é¢è² |
| | | headWriteFont.setColor(headColumnMap.get(cell.getStringCellValue())); |
| | | } |
| | | writeCellStyle.setWriteFont(headWriteFont); |
| | | CellStyle cellStyle = StyleUtil.buildCellStyle(workbook, null, writeCellStyle); |
| | | cell.setCellStyle(cellStyle); |
| | | |
| | | if (CollUtil.isNotEmpty(notationMap) && notationMap.containsKey(cell.getStringCellValue())) { |
| | | // æ¹æ³¨å
容 |
| | | String notationContext = notationMap.get(cell.getStringCellValue()); |
| | | // å建ç»å¾å¯¹è±¡ |
| | | Comment comment = drawing.createCellComment(new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), 0, (short) 5, 5)); |
| | | comment.setString(new XSSFRichTextString(notationContext)); |
| | | cell.setCellComment(comment); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è·åå¿
å¡«å |
| | | */ |
| | | private static Map<String, Short> getRequiredMap(Class<?> clazz) { |
| | | Map<String, Short> requiredMap = new HashMap<>(); |
| | | Field[] fields = clazz.getDeclaredFields(); |
| | | for (Field field : fields) { |
| | | if (!field.isAnnotationPresent(ExcelRequired.class)) { |
| | | continue; |
| | | } |
| | | ExcelRequired excelRequired = field.getAnnotation(ExcelRequired.class); |
| | | ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class); |
| | | requiredMap.put(excelProperty.value()[0], excelRequired.fontColor().getIndex()); |
| | | } |
| | | return requiredMap; |
| | | } |
| | | |
| | | /** |
| | | * è·åæ¹æ³¨ |
| | | */ |
| | | private static Map<String, String> getNotationMap(Class<?> clazz) { |
| | | Map<String, String> notationMap = new HashMap<>(); |
| | | Field[] fields = clazz.getDeclaredFields(); |
| | | for (Field field : fields) { |
| | | if (!field.isAnnotationPresent(ExcelNotation.class)) { |
| | | continue; |
| | | } |
| | | ExcelNotation excelNotation = field.getAnnotation(ExcelNotation.class); |
| | | ExcelProperty excelProperty = field.getAnnotation(ExcelProperty.class); |
| | | notationMap.put(excelProperty.value()[0], excelNotation.value()); |
| | | } |
| | | return notationMap; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.utils; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.io.resource.ClassPathResource; |
| | | import cn.hutool.core.util.IdUtil; |
| | | import cn.idev.excel.FastExcel; |
| | | import cn.idev.excel.ExcelWriter; |
| | | import cn.idev.excel.write.builder.ExcelWriterSheetBuilder; |
| | | import cn.idev.excel.write.metadata.WriteSheet; |
| | | import cn.idev.excel.write.metadata.fill.FillConfig; |
| | | import cn.idev.excel.write.metadata.fill.FillWrapper; |
| | | import cn.idev.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; |
| | | import jakarta.servlet.ServletOutputStream; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.core.utils.file.FileUtils; |
| | | import org.dromara.common.excel.convert.ExcelBigNumberConvert; |
| | | import org.dromara.common.excel.core.*; |
| | | import org.dromara.common.excel.handler.DataWriteHandler; |
| | | |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.io.OutputStream; |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.function.Consumer; |
| | | |
| | | /** |
| | | * Excelç¸å
³å¤ç |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE) |
| | | public class ExcelUtil { |
| | | |
| | | /** |
| | | * 忥坼å
¥(éç¨äºå°æ°æ®é) |
| | | * |
| | | * @param is è¾å
¥æµ |
| | | * @return 转æ¢åéå |
| | | */ |
| | | public static <T> List<T> importExcel(InputStream is, Class<T> clazz) { |
| | | return FastExcel.read(is).head(clazz).autoCloseStream(false).sheet().doReadSync(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * ä½¿ç¨æ ¡éªçå¬å¨ 弿¥å¯¼å
¥ 忥è¿å |
| | | * |
| | | * @param is è¾å
¥æµ |
| | | * @param clazz 对象类å |
| | | * @param isValidate æ¯å¦ Validator æ£éª é»è®¤ä¸ºæ¯ |
| | | * @return 转æ¢åéå |
| | | */ |
| | | public static <T> ExcelResult<T> importExcel(InputStream is, Class<T> clazz, boolean isValidate) { |
| | | DefaultExcelListener<T> listener = new DefaultExcelListener<>(isValidate); |
| | | FastExcel.read(is, clazz, listener).sheet().doRead(); |
| | | return listener.getExcelResult(); |
| | | } |
| | | |
| | | /** |
| | | * 使ç¨èªå®ä¹çå¬å¨ 弿¥å¯¼å
¥ èªå®ä¹è¿å |
| | | * |
| | | * @param is è¾å
¥æµ |
| | | * @param clazz 对象类å |
| | | * @param listener èªå®ä¹çå¬å¨ |
| | | * @return 转æ¢åéå |
| | | */ |
| | | public static <T> ExcelResult<T> importExcel(InputStream is, Class<T> clazz, ExcelListener<T> listener) { |
| | | FastExcel.read(is, clazz, listener).sheet().doRead(); |
| | | return listener.getExcelResult(); |
| | | } |
| | | |
| | | /** |
| | | * 导åºexcel |
| | | * |
| | | * @param list å¯¼åºæ°æ®éå |
| | | * @param sheetName å·¥ä½è¡¨çåç§° |
| | | * @param clazz å®ä½ç±» |
| | | * @param response ååºä½ |
| | | */ |
| | | public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, HttpServletResponse response) { |
| | | try { |
| | | resetResponse(sheetName, response); |
| | | ServletOutputStream os = response.getOutputStream(); |
| | | exportExcel(list, sheetName, clazz, false, os, null); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException("导åºExcelå¼å¸¸"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 导åºexcel |
| | | * |
| | | * @param list å¯¼åºæ°æ®éå |
| | | * @param sheetName å·¥ä½è¡¨çåç§° |
| | | * @param clazz å®ä½ç±» |
| | | * @param response ååºä½ |
| | | * @param options 级è䏿é |
| | | */ |
| | | public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, HttpServletResponse response, List<DropDownOptions> options) { |
| | | try { |
| | | resetResponse(sheetName, response); |
| | | ServletOutputStream os = response.getOutputStream(); |
| | | exportExcel(list, sheetName, clazz, false, os, options); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException("导åºExcelå¼å¸¸"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 导åºexcel |
| | | * |
| | | * @param list å¯¼åºæ°æ®éå |
| | | * @param sheetName å·¥ä½è¡¨çåç§° |
| | | * @param clazz å®ä½ç±» |
| | | * @param merge æ¯å¦åå¹¶åå
æ ¼ |
| | | * @param response ååºä½ |
| | | */ |
| | | public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, boolean merge, HttpServletResponse response) { |
| | | try { |
| | | resetResponse(sheetName, response); |
| | | ServletOutputStream os = response.getOutputStream(); |
| | | exportExcel(list, sheetName, clazz, merge, os, null); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException("导åºExcelå¼å¸¸"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 导åºexcel |
| | | * |
| | | * @param list å¯¼åºæ°æ®éå |
| | | * @param sheetName å·¥ä½è¡¨çåç§° |
| | | * @param clazz å®ä½ç±» |
| | | * @param merge æ¯å¦åå¹¶åå
æ ¼ |
| | | * @param response ååºä½ |
| | | * @param options 级è䏿é |
| | | */ |
| | | public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, boolean merge, HttpServletResponse response, List<DropDownOptions> options) { |
| | | try { |
| | | resetResponse(sheetName, response); |
| | | ServletOutputStream os = response.getOutputStream(); |
| | | exportExcel(list, sheetName, clazz, merge, os, options); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException("导åºExcelå¼å¸¸"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 导åºexcel |
| | | * |
| | | * @param list å¯¼åºæ°æ®éå |
| | | * @param sheetName å·¥ä½è¡¨çåç§° |
| | | * @param clazz å®ä½ç±» |
| | | * @param os è¾åºæµ |
| | | */ |
| | | public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, OutputStream os) { |
| | | exportExcel(list, sheetName, clazz, false, os, null); |
| | | } |
| | | |
| | | /** |
| | | * 导åºexcel |
| | | * |
| | | * @param list å¯¼åºæ°æ®éå |
| | | * @param sheetName å·¥ä½è¡¨çåç§° |
| | | * @param clazz å®ä½ç±» |
| | | * @param os è¾åºæµ |
| | | * @param options 级è䏿éå
容 |
| | | */ |
| | | public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, OutputStream os, List<DropDownOptions> options) { |
| | | exportExcel(list, sheetName, clazz, false, os, options); |
| | | } |
| | | |
| | | /** |
| | | * 导åºexcel |
| | | * |
| | | * @param list å¯¼åºæ°æ®éå |
| | | * @param sheetName å·¥ä½è¡¨çåç§° |
| | | * @param clazz å®ä½ç±» |
| | | * @param merge æ¯å¦åå¹¶åå
æ ¼ |
| | | * @param os è¾åºæµ |
| | | */ |
| | | public static <T> void exportExcel(List<T> list, String sheetName, Class<T> clazz, boolean merge, |
| | | OutputStream os, List<DropDownOptions> options) { |
| | | ExcelWriterSheetBuilder builder = FastExcel.write(os, clazz) |
| | | .autoCloseStream(false) |
| | | // èªå¨éé
|
| | | .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) |
| | | // 大æ°å¼èªå¨è½¬æ¢ 鲿¢å¤±ç |
| | | .registerConverter(new ExcelBigNumberConvert()) |
| | | .registerWriteHandler(new DataWriteHandler(clazz)) |
| | | .sheet(sheetName); |
| | | if (merge) { |
| | | // åå¹¶å¤çå¨ |
| | | builder.registerWriteHandler(new CellMergeStrategy(list, true)); |
| | | } |
| | | // æ·»å ä¸ææ¡æä½ |
| | | builder.registerWriteHandler(new ExcelDownHandler(options)); |
| | | builder.doWrite(list); |
| | | } |
| | | |
| | | /** |
| | | * 导åºexcel |
| | | * |
| | | * @param headType 带Excel注解çç±»å |
| | | * @param os è¾åºæµ |
| | | * @param options Excel䏿å¯é项 |
| | | * @param consumer 导åºå©ææ¶è´¹å½æ° |
| | | */ |
| | | public static <T> void exportExcel(Class<T> headType, OutputStream os, List<DropDownOptions> options, Consumer<ExcelWriterWrapper<T>> consumer) { |
| | | try (ExcelWriter writer = FastExcel.write(os, headType) |
| | | .autoCloseStream(false) |
| | | // èªå¨éé
|
| | | .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) |
| | | // 大æ°å¼èªå¨è½¬æ¢ 鲿¢å¤±ç |
| | | .registerConverter(new ExcelBigNumberConvert()) |
| | | // æ¹æ³¨å¿
填项å¤ç |
| | | .registerWriteHandler(new DataWriteHandler(headType)) |
| | | // æ·»å ä¸ææ¡æä½ |
| | | .registerWriteHandler(new ExcelDownHandler(options)) |
| | | .build()) { |
| | | // æ§è¡æ¶è´¹å½æ° |
| | | consumer.accept(ExcelWriterWrapper.of(writer)); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 导åºexcel |
| | | * |
| | | * @param headType 带Excel注解çç±»å |
| | | * @param os è¾åºæµ |
| | | * @param consumer 导åºå©ææ¶è´¹å½æ° |
| | | */ |
| | | public static <T> void exportExcel(Class<T> headType, OutputStream os, Consumer<ExcelWriterWrapper<T>> consumer) { |
| | | exportExcel(headType, os, null, consumer); |
| | | } |
| | | |
| | | /** |
| | | * åè¡¨å¤æ°æ®æ¨¡æ¿å¯¼åº æ¨¡æ¿æ ¼å¼ä¸º {.屿§} |
| | | * |
| | | * @param filename æä»¶å |
| | | * @param templatePath 模æ¿è·¯å¾ resource ç®å½ä¸çè·¯å¾å
æ¬æ¨¡æ¿æä»¶å |
| | | * ä¾å¦: excel/temp.xlsx |
| | | * éç¹: æ¨¡æ¿æä»¶å¿
é¡»æ¾ç½®å°å¯å¨ç±»å¯¹åºç resource ç®å½ä¸ |
| | | * @param data 模æ¿éè¦çæ°æ® |
| | | * @param response ååºä½ |
| | | */ |
| | | public static <T> void exportTemplate(List<T> data, String filename, String templatePath, HttpServletResponse response) { |
| | | try { |
| | | if (CollUtil.isEmpty(data)) { |
| | | throw new IllegalArgumentException("æ°æ®ä¸ºç©º"); |
| | | } |
| | | resetResponse(filename, response); |
| | | ServletOutputStream os = response.getOutputStream(); |
| | | exportTemplate(data, templatePath, os); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException("导åºExcelå¼å¸¸"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * åè¡¨å¤æ°æ®æ¨¡æ¿å¯¼åº æ¨¡æ¿æ ¼å¼ä¸º {.屿§} |
| | | * |
| | | * @param templatePath 模æ¿è·¯å¾ resource ç®å½ä¸çè·¯å¾å
æ¬æ¨¡æ¿æä»¶å |
| | | * ä¾å¦: excel/temp.xlsx |
| | | * éç¹: æ¨¡æ¿æä»¶å¿
é¡»æ¾ç½®å°å¯å¨ç±»å¯¹åºç resource ç®å½ä¸ |
| | | * @param data 模æ¿éè¦çæ°æ® |
| | | * @param os è¾åºæµ |
| | | */ |
| | | public static <T> void exportTemplate(List<T> data, String templatePath, OutputStream os) { |
| | | ClassPathResource templateResource = new ClassPathResource(templatePath); |
| | | ExcelWriter excelWriter = FastExcel.write(os) |
| | | .withTemplate(templateResource.getStream()) |
| | | .autoCloseStream(false) |
| | | // 大æ°å¼èªå¨è½¬æ¢ 鲿¢å¤±ç |
| | | .registerConverter(new ExcelBigNumberConvert()) |
| | | .registerWriteHandler(new DataWriteHandler(data.get(0).getClass())) |
| | | .build(); |
| | | WriteSheet writeSheet = FastExcel.writerSheet().build(); |
| | | FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build(); |
| | | // åè¡¨å¤æ°æ®å¯¼åº æ¨¡æ¿æ ¼å¼ä¸º {.屿§} |
| | | for (T d : data) { |
| | | excelWriter.fill(d, fillConfig, writeSheet); |
| | | } |
| | | excelWriter.finish(); |
| | | } |
| | | |
| | | /** |
| | | * å¤è¡¨å¤æ°æ®æ¨¡æ¿å¯¼åº æ¨¡æ¿æ ¼å¼ä¸º {key.屿§} |
| | | * |
| | | * @param filename æä»¶å |
| | | * @param templatePath 模æ¿è·¯å¾ resource ç®å½ä¸çè·¯å¾å
æ¬æ¨¡æ¿æä»¶å |
| | | * ä¾å¦: excel/temp.xlsx |
| | | * éç¹: æ¨¡æ¿æä»¶å¿
é¡»æ¾ç½®å°å¯å¨ç±»å¯¹åºç resource ç®å½ä¸ |
| | | * @param data 模æ¿éè¦çæ°æ® |
| | | * @param response ååºä½ |
| | | */ |
| | | public static void exportTemplateMultiList(Map<String, Object> data, String filename, String templatePath, HttpServletResponse response) { |
| | | try { |
| | | if (CollUtil.isEmpty(data)) { |
| | | throw new IllegalArgumentException("æ°æ®ä¸ºç©º"); |
| | | } |
| | | resetResponse(filename, response); |
| | | ServletOutputStream os = response.getOutputStream(); |
| | | exportTemplateMultiList(data, templatePath, os); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException("导åºExcelå¼å¸¸"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å¤sheet模æ¿å¯¼åº æ¨¡æ¿æ ¼å¼ä¸º {key.屿§} |
| | | * |
| | | * @param filename æä»¶å |
| | | * @param templatePath 模æ¿è·¯å¾ resource ç®å½ä¸çè·¯å¾å
æ¬æ¨¡æ¿æä»¶å |
| | | * ä¾å¦: excel/temp.xlsx |
| | | * éç¹: æ¨¡æ¿æä»¶å¿
é¡»æ¾ç½®å°å¯å¨ç±»å¯¹åºç resource ç®å½ä¸ |
| | | * @param data 模æ¿éè¦çæ°æ® |
| | | * @param response ååºä½ |
| | | */ |
| | | public static void exportTemplateMultiSheet(List<Map<String, Object>> data, String filename, String templatePath, HttpServletResponse response) { |
| | | try { |
| | | if (CollUtil.isEmpty(data)) { |
| | | throw new IllegalArgumentException("æ°æ®ä¸ºç©º"); |
| | | } |
| | | resetResponse(filename, response); |
| | | ServletOutputStream os = response.getOutputStream(); |
| | | exportTemplateMultiSheet(data, templatePath, os); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException("导åºExcelå¼å¸¸"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å¤è¡¨å¤æ°æ®æ¨¡æ¿å¯¼åº æ¨¡æ¿æ ¼å¼ä¸º {key.屿§} |
| | | * |
| | | * @param templatePath 模æ¿è·¯å¾ resource ç®å½ä¸çè·¯å¾å
æ¬æ¨¡æ¿æä»¶å |
| | | * ä¾å¦: excel/temp.xlsx |
| | | * éç¹: æ¨¡æ¿æä»¶å¿
é¡»æ¾ç½®å°å¯å¨ç±»å¯¹åºç resource ç®å½ä¸ |
| | | * @param data 模æ¿éè¦çæ°æ® |
| | | * @param os è¾åºæµ |
| | | */ |
| | | public static void exportTemplateMultiList(Map<String, Object> data, String templatePath, OutputStream os) { |
| | | ClassPathResource templateResource = new ClassPathResource(templatePath); |
| | | ExcelWriter excelWriter = FastExcel.write(os) |
| | | .withTemplate(templateResource.getStream()) |
| | | .autoCloseStream(false) |
| | | // 大æ°å¼èªå¨è½¬æ¢ 鲿¢å¤±ç |
| | | .registerConverter(new ExcelBigNumberConvert()) |
| | | .build(); |
| | | WriteSheet writeSheet = FastExcel.writerSheet().build(); |
| | | for (Map.Entry<String, Object> map : data.entrySet()) { |
| | | // 设置å表åç»è¿ææ°æ® |
| | | FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build(); |
| | | if (map.getValue() instanceof Collection) { |
| | | // å¤è¡¨å¯¼åºå¿
é¡»ä½¿ç¨ FillWrapper |
| | | excelWriter.fill(new FillWrapper(map.getKey(), (Collection<?>) map.getValue()), fillConfig, writeSheet); |
| | | } else { |
| | | excelWriter.fill(map.getValue(), fillConfig, writeSheet); |
| | | } |
| | | } |
| | | excelWriter.finish(); |
| | | } |
| | | |
| | | /** |
| | | * å¤sheet模æ¿å¯¼åº æ¨¡æ¿æ ¼å¼ä¸º {key.屿§} |
| | | * |
| | | * @param templatePath 模æ¿è·¯å¾ resource ç®å½ä¸çè·¯å¾å
æ¬æ¨¡æ¿æä»¶å |
| | | * ä¾å¦: excel/temp.xlsx |
| | | * éç¹: æ¨¡æ¿æä»¶å¿
é¡»æ¾ç½®å°å¯å¨ç±»å¯¹åºç resource ç®å½ä¸ |
| | | * @param data 模æ¿éè¦çæ°æ® |
| | | * @param os è¾åºæµ |
| | | */ |
| | | public static void exportTemplateMultiSheet(List<Map<String, Object>> data, String templatePath, OutputStream os) { |
| | | ClassPathResource templateResource = new ClassPathResource(templatePath); |
| | | ExcelWriter excelWriter = FastExcel.write(os) |
| | | .withTemplate(templateResource.getStream()) |
| | | .autoCloseStream(false) |
| | | // 大æ°å¼èªå¨è½¬æ¢ 鲿¢å¤±ç |
| | | .registerConverter(new ExcelBigNumberConvert()) |
| | | .build(); |
| | | for (int i = 0; i < data.size(); i++) { |
| | | WriteSheet writeSheet = FastExcel.writerSheet(i).build(); |
| | | for (Map.Entry<String, Object> map : data.get(i).entrySet()) { |
| | | // 设置å表åç»è¿ææ°æ® |
| | | FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build(); |
| | | if (map.getValue() instanceof Collection) { |
| | | // å¤è¡¨å¯¼åºå¿
é¡»ä½¿ç¨ FillWrapper |
| | | excelWriter.fill(new FillWrapper(map.getKey(), (Collection<?>) map.getValue()), fillConfig, writeSheet); |
| | | } else { |
| | | excelWriter.fill(map.getValue(), writeSheet); |
| | | } |
| | | } |
| | | } |
| | | excelWriter.finish(); |
| | | } |
| | | |
| | | /** |
| | | * éç½®ååºä½ |
| | | */ |
| | | private static void resetResponse(String sheetName, HttpServletResponse response) throws UnsupportedEncodingException { |
| | | String filename = encodingFilename(sheetName); |
| | | FileUtils.setAttachmentResponseHeader(response, filename); |
| | | response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8"); |
| | | } |
| | | |
| | | /** |
| | | * è§£æå¯¼åºå¼ 0=ç·,1=女,2=æªç¥ |
| | | * |
| | | * @param propertyValue åæ°å¼ |
| | | * @param converterExp ç¿»è¯æ³¨è§£ |
| | | * @param separator åé符 |
| | | * @return è§£æåå¼ |
| | | */ |
| | | public static String convertByExp(String propertyValue, String converterExp, String separator) { |
| | | StringBuilder propertyString = new StringBuilder(); |
| | | String[] convertSource = converterExp.split(StringUtils.SEPARATOR); |
| | | for (String item : convertSource) { |
| | | String[] itemArray = item.split("="); |
| | | if (StringUtils.containsAny(propertyValue, separator)) { |
| | | for (String value : propertyValue.split(separator)) { |
| | | if (itemArray[0].equals(value)) { |
| | | propertyString.append(itemArray[1] + separator); |
| | | break; |
| | | } |
| | | } |
| | | } else { |
| | | if (itemArray[0].equals(propertyValue)) { |
| | | return itemArray[1]; |
| | | } |
| | | } |
| | | } |
| | | return StringUtils.stripEnd(propertyString.toString(), separator); |
| | | } |
| | | |
| | | /** |
| | | * ååè§£æå¼ ç·=0,女=1,æªç¥=2 |
| | | * |
| | | * @param propertyValue åæ°å¼ |
| | | * @param converterExp ç¿»è¯æ³¨è§£ |
| | | * @param separator åé符 |
| | | * @return è§£æåå¼ |
| | | */ |
| | | public static String reverseByExp(String propertyValue, String converterExp, String separator) { |
| | | StringBuilder propertyString = new StringBuilder(); |
| | | String[] convertSource = converterExp.split(StringUtils.SEPARATOR); |
| | | for (String item : convertSource) { |
| | | String[] itemArray = item.split("="); |
| | | if (StringUtils.containsAny(propertyValue, separator)) { |
| | | for (String value : propertyValue.split(separator)) { |
| | | if (itemArray[1].equals(value)) { |
| | | propertyString.append(itemArray[0] + separator); |
| | | break; |
| | | } |
| | | } |
| | | } else { |
| | | if (itemArray[1].equals(propertyValue)) { |
| | | return itemArray[0]; |
| | | } |
| | | } |
| | | } |
| | | return StringUtils.stripEnd(propertyString.toString(), separator); |
| | | } |
| | | |
| | | /** |
| | | * ç¼ç æä»¶å |
| | | */ |
| | | public static String encodingFilename(String filename) { |
| | | return IdUtil.fastSimpleUUID() + "_" + filename + ".xlsx"; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.excel.utils; |
| | | |
| | | import cn.idev.excel.ExcelWriter; |
| | | import cn.idev.excel.FastExcel; |
| | | import cn.idev.excel.context.WriteContext; |
| | | import cn.idev.excel.write.builder.ExcelWriterSheetBuilder; |
| | | import cn.idev.excel.write.builder.ExcelWriterTableBuilder; |
| | | import cn.idev.excel.write.metadata.WriteSheet; |
| | | import cn.idev.excel.write.metadata.WriteTable; |
| | | import cn.idev.excel.write.metadata.fill.FillConfig; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.function.Supplier; |
| | | |
| | | /** |
| | | * ExcelWriterWrapper Excelååºå
è£
å¨ |
| | | * <br> |
| | | * æä¾äºä¸ç»ä¸ ExcelWriter ä¸ä¸å¯¹åºçååºæ¹æ³ï¼é¿å
ç´æ¥æä¾ ExcelWriter è导è´çä¸äºä¸å¯æ§é®é¢ï¼æ¯å¦æåå
³éäºIOæµçï¼ |
| | | * |
| | | * @author ç§è¾æªå¯ |
| | | * @see ExcelWriter |
| | | */ |
| | | public record ExcelWriterWrapper<T>(ExcelWriter excelWriter) { |
| | | |
| | | public void write(Collection<T> data, WriteSheet writeSheet) { |
| | | excelWriter.write(data, writeSheet); |
| | | } |
| | | |
| | | public void write(Supplier<Collection<T>> supplier, WriteSheet writeSheet) { |
| | | excelWriter.write(supplier.get(), writeSheet); |
| | | } |
| | | |
| | | public void write(Collection<T> data, WriteSheet writeSheet, WriteTable writeTable) { |
| | | excelWriter.write(data, writeSheet, writeTable); |
| | | } |
| | | |
| | | public void write(Supplier<Collection<T>> supplier, WriteSheet writeSheet, WriteTable writeTable) { |
| | | excelWriter.write(supplier.get(), writeSheet, writeTable); |
| | | } |
| | | |
| | | public void fill(Object data, WriteSheet writeSheet) { |
| | | excelWriter.fill(data, writeSheet); |
| | | } |
| | | |
| | | public void fill(Object data, FillConfig fillConfig, WriteSheet writeSheet) { |
| | | excelWriter.fill(data, fillConfig, writeSheet); |
| | | } |
| | | |
| | | public void fill(Supplier<Object> supplier, WriteSheet writeSheet) { |
| | | excelWriter.fill(supplier, writeSheet); |
| | | } |
| | | |
| | | public void fill(Supplier<Object> supplier, FillConfig fillConfig, WriteSheet writeSheet) { |
| | | excelWriter.fill(supplier, fillConfig, writeSheet); |
| | | } |
| | | |
| | | public WriteContext writeContext() { |
| | | return excelWriter.writeContext(); |
| | | } |
| | | |
| | | /** |
| | | * å建ä¸ä¸ª ExcelWriterWrapper |
| | | * |
| | | * @param excelWriter ExcelWriter |
| | | * @return ExcelWriterWrapper |
| | | */ |
| | | public static <T> ExcelWriterWrapper<T> of(ExcelWriter excelWriter) { |
| | | return new ExcelWriterWrapper<>(excelWriter); |
| | | } |
| | | |
| | | // -------------------------------- sheet start |
| | | |
| | | public static WriteSheet buildSheet(Integer sheetNo, String sheetName) { |
| | | return sheetBuilder(sheetNo, sheetName).build(); |
| | | } |
| | | |
| | | public static WriteSheet buildSheet(Integer sheetNo) { |
| | | return sheetBuilder(sheetNo).build(); |
| | | } |
| | | |
| | | public static WriteSheet buildSheet(String sheetName) { |
| | | return sheetBuilder(sheetName).build(); |
| | | } |
| | | |
| | | public static WriteSheet buildSheet() { |
| | | return sheetBuilder().build(); |
| | | } |
| | | |
| | | public static ExcelWriterSheetBuilder sheetBuilder(Integer sheetNo, String sheetName) { |
| | | return FastExcel.writerSheet(sheetNo, sheetName); |
| | | } |
| | | |
| | | public static ExcelWriterSheetBuilder sheetBuilder(Integer sheetNo) { |
| | | return FastExcel.writerSheet(sheetNo); |
| | | } |
| | | |
| | | public static ExcelWriterSheetBuilder sheetBuilder(String sheetName) { |
| | | return FastExcel.writerSheet(sheetName); |
| | | } |
| | | |
| | | public static ExcelWriterSheetBuilder sheetBuilder() { |
| | | return FastExcel.writerSheet(); |
| | | } |
| | | |
| | | // -------------------------------- sheet end |
| | | |
| | | // -------------------------------- table start |
| | | |
| | | public static WriteTable buildTable(Integer tableNo) { |
| | | return tableBuilder(tableNo).build(); |
| | | } |
| | | |
| | | public static WriteTable buildTable() { |
| | | return tableBuilder().build(); |
| | | } |
| | | |
| | | public static ExcelWriterTableBuilder tableBuilder(Integer tableNo) { |
| | | return FastExcel.writerTable(tableNo); |
| | | } |
| | | |
| | | public static ExcelWriterTableBuilder tableBuilder() { |
| | | return FastExcel.writerTable(); |
| | | } |
| | | |
| | | // -------------------------------- table end |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>5.5.3</version> |
| | | </parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-idempotent</artifactId> |
| | | <version>5.5.3</version> |
| | | <description>ruoyi-common-idempotent å¹çåè½</description> |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-json</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-redis</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>cn.hutool</groupId> |
| | | <artifactId>hutool-crypto</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>cn.dev33</groupId> |
| | | <artifactId>sa-token-core</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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"> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>${revision}</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>ruoyi-common-idempotent</artifactId> |
| | | |
| | | <description> |
| | | ruoyi-common-idempotent å¹çåè½ |
| | | </description> |
| | | |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-json</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-redis</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>cn.hutool</groupId> |
| | | <artifactId>hutool-crypto</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>cn.dev33</groupId> |
| | | <artifactId>sa-token-core</artifactId> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.idempotent.annotation; |
| | | |
| | | import java.lang.annotation.*; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * èªå®ä¹æ³¨è§£é²æ¢è¡¨åéå¤æäº¤ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Inherited |
| | | @Target(ElementType.METHOD) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @Documented |
| | | public @interface RepeatSubmit { |
| | | |
| | | /** |
| | | * é´éæ¶é´(ms)ï¼å°äºæ¤æ¶é´è§ä¸ºéå¤æäº¤ |
| | | */ |
| | | int interval() default 5000; |
| | | |
| | | TimeUnit timeUnit() default TimeUnit.MILLISECONDS; |
| | | |
| | | /** |
| | | * æç¤ºæ¶æ¯ æ¯æå½é
å æ ¼å¼ä¸º {code} |
| | | */ |
| | | String message() default "{repeat.submit.message}"; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.idempotent.aspectj; |
| | | |
| | | import cn.dev33.satoken.SaManager; |
| | | import cn.hutool.core.util.ArrayUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import cn.hutool.crypto.SecureUtil; |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import org.aspectj.lang.JoinPoint; |
| | | import org.aspectj.lang.annotation.AfterReturning; |
| | | import org.aspectj.lang.annotation.AfterThrowing; |
| | | import org.aspectj.lang.annotation.Aspect; |
| | | import org.aspectj.lang.annotation.Before; |
| | | import org.dromara.common.core.constant.GlobalConstants; |
| | | import org.dromara.common.core.domain.R; |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | import org.dromara.common.core.utils.MessageUtils; |
| | | import org.dromara.common.core.utils.ServletUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.idempotent.annotation.RepeatSubmit; |
| | | import org.dromara.common.json.utils.JsonUtils; |
| | | import org.dromara.common.redis.utils.RedisUtils; |
| | | import org.springframework.validation.BindingResult; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.time.Duration; |
| | | import java.util.Collection; |
| | | import java.util.Map; |
| | | import java.util.StringJoiner; |
| | | |
| | | /** |
| | | * 鲿¢éå¤æäº¤(åèç¾å¢GTISé²éç³»ç») |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Aspect |
| | | public class RepeatSubmitAspect { |
| | | |
| | | private static final ThreadLocal<String> KEY_CACHE = new ThreadLocal<>(); |
| | | |
| | | @Before("@annotation(repeatSubmit)") |
| | | public void doBefore(JoinPoint point, RepeatSubmit repeatSubmit) throws Throwable { |
| | | // å¦ææ³¨è§£ä¸ä¸º0 åä½¿ç¨æ³¨è§£æ°å¼ |
| | | long interval = repeatSubmit.timeUnit().toMillis(repeatSubmit.interval()); |
| | | |
| | | if (interval < 1000) { |
| | | throw new ServiceException("éå¤æäº¤é´éæ¶é´ä¸è½å°äº'1'ç§"); |
| | | } |
| | | HttpServletRequest request = ServletUtils.getRequest(); |
| | | String nowParams = argsArrayToString(point.getArgs()); |
| | | |
| | | // 请æ±å°åï¼ä½ä¸ºåæ¾cacheçkeyå¼ï¼ |
| | | String url = request.getRequestURI(); |
| | | |
| | | // å¯ä¸å¼ï¼æ²¡ææ¶æ¯å¤´å使ç¨è¯·æ±å°åï¼ |
| | | String submitKey = StringUtils.trimToEmpty(request.getHeader(SaManager.getConfig().getTokenName())); |
| | | |
| | | submitKey = SecureUtil.md5(submitKey + ":" + nowParams); |
| | | // å¯ä¸æ è¯ï¼æå®key + url + æ¶æ¯å¤´ï¼ |
| | | String cacheRepeatKey = GlobalConstants.REPEAT_SUBMIT_KEY + url + submitKey; |
| | | if (RedisUtils.setObjectIfAbsent(cacheRepeatKey, "", Duration.ofMillis(interval))) { |
| | | KEY_CACHE.set(cacheRepeatKey); |
| | | } else { |
| | | String message = repeatSubmit.message(); |
| | | if (StringUtils.startsWith(message, "{") && StringUtils.endsWith(message, "}")) { |
| | | message = MessageUtils.message(StringUtils.substring(message, 1, message.length() - 1)); |
| | | } |
| | | throw new ServiceException(message); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å¤çå®è¯·æ±åæ§è¡ |
| | | * |
| | | * @param joinPoint åç¹ |
| | | */ |
| | | @AfterReturning(pointcut = "@annotation(repeatSubmit)", returning = "jsonResult") |
| | | public void doAfterReturning(JoinPoint joinPoint, RepeatSubmit repeatSubmit, Object jsonResult) { |
| | | if (jsonResult instanceof R<?> r) { |
| | | try { |
| | | // æååä¸å é¤redisæ°æ® ä¿è¯å¨æææ¶é´å
æ æ³éå¤æäº¤ |
| | | if (r.getCode() == R.SUCCESS) { |
| | | return; |
| | | } |
| | | RedisUtils.deleteObject(KEY_CACHE.get()); |
| | | } finally { |
| | | KEY_CACHE.remove(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ¦æªå¼å¸¸æä½ |
| | | * |
| | | * @param joinPoint åç¹ |
| | | * @param e å¼å¸¸ |
| | | */ |
| | | @AfterThrowing(value = "@annotation(repeatSubmit)", throwing = "e") |
| | | public void doAfterThrowing(JoinPoint joinPoint, RepeatSubmit repeatSubmit, Exception e) { |
| | | RedisUtils.deleteObject(KEY_CACHE.get()); |
| | | KEY_CACHE.remove(); |
| | | } |
| | | |
| | | /** |
| | | * åæ°æ¼è£
|
| | | */ |
| | | private String argsArrayToString(Object[] paramsArray) { |
| | | StringJoiner params = new StringJoiner(" "); |
| | | if (ArrayUtil.isEmpty(paramsArray)) { |
| | | return params.toString(); |
| | | } |
| | | for (Object o : paramsArray) { |
| | | if (ObjectUtil.isNotNull(o) && !isFilterObject(o)) { |
| | | params.add(JsonUtils.toJsonString(o)); |
| | | } |
| | | } |
| | | return params.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦éè¦è¿æ»¤ç对象ã |
| | | * |
| | | * @param o 对象信æ¯ã |
| | | * @return 妿æ¯éè¦è¿æ»¤ç对象ï¼åè¿åtrueï¼å¦åè¿åfalseã |
| | | */ |
| | | @SuppressWarnings("rawtypes") |
| | | public boolean isFilterObject(final Object o) { |
| | | Class<?> clazz = o.getClass(); |
| | | if (clazz.isArray()) { |
| | | return MultipartFile.class.isAssignableFrom(clazz.getComponentType()); |
| | | } else if (Collection.class.isAssignableFrom(clazz)) { |
| | | Collection collection = (Collection) o; |
| | | for (Object value : collection) { |
| | | return value instanceof MultipartFile; |
| | | } |
| | | } else if (Map.class.isAssignableFrom(clazz)) { |
| | | Map map = (Map) o; |
| | | for (Object value : map.values()) { |
| | | return value instanceof MultipartFile; |
| | | } |
| | | } |
| | | return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse |
| | | || o instanceof BindingResult; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.idempotent.config; |
| | | |
| | | import org.dromara.common.idempotent.aspectj.RepeatSubmitAspect; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.data.redis.connection.RedisConfiguration; |
| | | |
| | | /** |
| | | * å¹çåè½é
ç½® |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @AutoConfiguration(after = RedisConfiguration.class) |
| | | public class IdempotentConfig { |
| | | |
| | | @Bean |
| | | public RepeatSubmitAspect repeatSubmitAspect() { |
| | | return new RepeatSubmitAspect(); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | org.dromara.common.idempotent.config.IdempotentConfig |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>5.5.3</version> |
| | | </parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-job</artifactId> |
| | | <version>5.5.3</version> |
| | | <description>ruoyi-common-job 宿¶ä»»å¡</description> |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-autoconfigure</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.aizuda</groupId> |
| | | <artifactId>snail-job-client-starter</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.aizuda</groupId> |
| | | <artifactId>snail-job-client-job-core</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.projectlombok</groupId> |
| | | <artifactId>lombok</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>${revision}</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>ruoyi-common-job</artifactId> |
| | | |
| | | <description> |
| | | ruoyi-common-job 宿¶ä»»å¡ |
| | | </description> |
| | | |
| | | <dependencies> |
| | | |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-autoconfigure</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- SnailJob client --> |
| | | <dependency> |
| | | <groupId>com.aizuda</groupId> |
| | | <artifactId>snail-job-client-starter</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.aizuda</groupId> |
| | | <artifactId>snail-job-client-job-core</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.projectlombok</groupId> |
| | | <artifactId>lombok</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.job.config; |
| | | |
| | | import ch.qos.logback.classic.Logger; |
| | | import ch.qos.logback.classic.LoggerContext; |
| | | import ch.qos.logback.classic.spi.ILoggingEvent; |
| | | import com.aizuda.snailjob.client.common.appender.SnailLogbackAppender; |
| | | import com.aizuda.snailjob.client.common.event.SnailClientStartingEvent; |
| | | import com.aizuda.snailjob.client.starter.EnableSnailJob; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.context.event.EventListener; |
| | | import org.springframework.scheduling.annotation.EnableScheduling; |
| | | |
| | | /** |
| | | * å¯å¨å®æ¶ä»»å¡ |
| | | * |
| | | * @author opensnail |
| | | * @date 2024-05-17 |
| | | */ |
| | | @AutoConfiguration |
| | | @ConditionalOnProperty(prefix = "snail-job", name = "enabled", havingValue = "true") |
| | | @EnableScheduling |
| | | @EnableSnailJob |
| | | public class SnailJobConfig { |
| | | |
| | | @EventListener(SnailClientStartingEvent.class) |
| | | public void onStarting(SnailClientStartingEvent event) { |
| | | LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); |
| | | SnailLogbackAppender<ILoggingEvent> ca = new SnailLogbackAppender<>(); |
| | | ca.setName("snail_log_appender"); |
| | | ca.start(); |
| | | Logger rootLogger = lc.getLogger(Logger.ROOT_LOGGER_NAME); |
| | | rootLogger.addAppender(ca); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | org.dromara.common.job.config.SnailJobConfig |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>5.5.3</version> |
| | | </parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-json</artifactId> |
| | | <version>5.5.3</version> |
| | | <description>ruoyi-common-json åºå忍¡å</description> |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.fasterxml.jackson.core</groupId> |
| | | <artifactId>jackson-databind</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.fasterxml.jackson.datatype</groupId> |
| | | <artifactId>jackson-datatype-jsr310</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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"> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>${revision}</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>ruoyi-common-json</artifactId> |
| | | |
| | | <description> |
| | | ruoyi-common-json åºå忍¡å |
| | | </description> |
| | | |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- JSONå·¥å
·ç±» --> |
| | | <dependency> |
| | | <groupId>com.fasterxml.jackson.core</groupId> |
| | | <artifactId>jackson-databind</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.fasterxml.jackson.datatype</groupId> |
| | | <artifactId>jackson-datatype-jsr310</artifactId> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.json.config; |
| | | |
| | | import com.fasterxml.jackson.databind.Module; |
| | | import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; |
| | | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; |
| | | import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; |
| | | import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.json.handler.BigNumberSerializer; |
| | | import org.dromara.common.json.handler.CustomDateDeserializer; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; |
| | | import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; |
| | | import org.springframework.context.annotation.Bean; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.BigInteger; |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.Date; |
| | | import java.util.TimeZone; |
| | | |
| | | /** |
| | | * jackson é
ç½® |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Slf4j |
| | | @AutoConfiguration(before = JacksonAutoConfiguration.class) |
| | | public class JacksonConfig { |
| | | |
| | | @Bean |
| | | public Module registerJavaTimeModule() { |
| | | // å
¨å±é
ç½®åºååè¿å JSON å¤ç |
| | | JavaTimeModule javaTimeModule = new JavaTimeModule(); |
| | | javaTimeModule.addSerializer(Long.class, BigNumberSerializer.INSTANCE); |
| | | javaTimeModule.addSerializer(Long.TYPE, BigNumberSerializer.INSTANCE); |
| | | javaTimeModule.addSerializer(BigInteger.class, BigNumberSerializer.INSTANCE); |
| | | javaTimeModule.addSerializer(BigDecimal.class, ToStringSerializer.instance); |
| | | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); |
| | | javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter)); |
| | | javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter)); |
| | | javaTimeModule.addDeserializer(Date.class, new CustomDateDeserializer()); |
| | | return javaTimeModule; |
| | | } |
| | | |
| | | @Bean |
| | | public Jackson2ObjectMapperBuilderCustomizer customizer() { |
| | | return builder -> { |
| | | builder.timeZone(TimeZone.getDefault()); |
| | | log.info("åå§å jackson é
ç½®"); |
| | | }; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.json.handler; |
| | | |
| | | import com.fasterxml.jackson.core.JsonGenerator; |
| | | import com.fasterxml.jackson.databind.SerializerProvider; |
| | | import com.fasterxml.jackson.databind.annotation.JacksonStdImpl; |
| | | import com.fasterxml.jackson.databind.ser.std.NumberSerializer; |
| | | |
| | | import java.io.IOException; |
| | | |
| | | /** |
| | | * è¶
åº JS æå¤§æå°å¼ å¤ç |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @JacksonStdImpl |
| | | public class BigNumberSerializer extends NumberSerializer { |
| | | |
| | | /** |
| | | * æ ¹æ® JS Number.MAX_SAFE_INTEGER ä¸ Number.MIN_SAFE_INTEGER 徿¥ |
| | | */ |
| | | private static final long MAX_SAFE_INTEGER = 9007199254740991L; |
| | | private static final long MIN_SAFE_INTEGER = -9007199254740991L; |
| | | |
| | | /** |
| | | * æä¾å®ä¾ |
| | | */ |
| | | public static final BigNumberSerializer INSTANCE = new BigNumberSerializer(Number.class); |
| | | |
| | | public BigNumberSerializer(Class<? extends Number> rawType) { |
| | | super(rawType); |
| | | } |
| | | |
| | | @Override |
| | | public void serialize(Number value, JsonGenerator gen, SerializerProvider provider) throws IOException { |
| | | // è¶
åºèå´ åºåå为å符串 |
| | | if (value.longValue() > MIN_SAFE_INTEGER && value.longValue() < MAX_SAFE_INTEGER) { |
| | | super.serialize(value, gen, provider); |
| | | } else { |
| | | gen.writeString(value.toString()); |
| | | } |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.json.handler; |
| | | |
| | | import cn.hutool.core.date.DateTime; |
| | | import cn.hutool.core.date.DateUtil; |
| | | import com.fasterxml.jackson.core.JsonParser; |
| | | import com.fasterxml.jackson.databind.DeserializationContext; |
| | | import com.fasterxml.jackson.databind.JsonDeserializer; |
| | | import org.dromara.common.core.utils.ObjectUtils; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * èªå®ä¹ Date ç±»åååºååå¤çå¨ï¼æ¯æå¤ç§æ ¼å¼ï¼ |
| | | * |
| | | * @author AprilWind |
| | | */ |
| | | public class CustomDateDeserializer extends JsonDeserializer<Date> { |
| | | |
| | | /** |
| | | * ååºååé»è¾ï¼å°å符串转æ¢ä¸º Date 对象 |
| | | * |
| | | * @param p JSON è§£æå¨ï¼ç¨äºè·ååç¬¦ä¸²å¼ |
| | | * @param ctxt ä¸ä¸æç¯å¢ï¼å¯ç¨äºè·åæ´å¤é
ç½®ï¼ |
| | | * @return 转æ¢åç Date 对象ï¼è¥ä¸ºç©ºå符串è¿å null |
| | | * @throws IOException å½åç¬¦ä¸²æ ¼å¼éæ³æè½¬æ¢å¤±è´¥æ¶æåº |
| | | */ |
| | | @Override |
| | | public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { |
| | | DateTime parse = DateUtil.parse(p.getText()); |
| | | if (ObjectUtils.isNull(parse)) { |
| | | return null; |
| | | } |
| | | return parse.toJdkDate(); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.json.utils; |
| | | |
| | | import cn.hutool.core.lang.Dict; |
| | | import cn.hutool.core.util.ArrayUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.fasterxml.jackson.core.JsonProcessingException; |
| | | import com.fasterxml.jackson.core.type.TypeReference; |
| | | import com.fasterxml.jackson.databind.JsonNode; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import com.fasterxml.jackson.databind.exc.MismatchedInputException; |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * JSON å·¥å
·ç±» |
| | | * |
| | | * @author èéæºç |
| | | */ |
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE) |
| | | public class JsonUtils { |
| | | |
| | | private static final ObjectMapper OBJECT_MAPPER = SpringUtils.getBean(ObjectMapper.class); |
| | | |
| | | public static ObjectMapper getObjectMapper() { |
| | | return OBJECT_MAPPER; |
| | | } |
| | | |
| | | /** |
| | | * å°å¯¹è±¡è½¬æ¢ä¸ºJSONæ ¼å¼çå符串 |
| | | * |
| | | * @param object è¦è½¬æ¢ç对象 |
| | | * @return JSONæ ¼å¼çå符串ï¼å¦æå¯¹è±¡ä¸ºnullï¼åè¿ånull |
| | | * @throws RuntimeException å¦æè½¬æ¢è¿ç¨ä¸åçJSONå¤çå¼å¸¸ï¼åæåºè¿è¡æ¶å¼å¸¸ |
| | | */ |
| | | public static String toJsonString(Object object) { |
| | | if (ObjectUtil.isNull(object)) { |
| | | return null; |
| | | } |
| | | try { |
| | | return OBJECT_MAPPER.writeValueAsString(object); |
| | | } catch (JsonProcessingException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°JSONæ ¼å¼çå符串转æ¢ä¸ºæå®ç±»åç对象 |
| | | * |
| | | * @param text JSONæ ¼å¼çå符串 |
| | | * @param clazz è¦è½¬æ¢çç®æ 对象类å |
| | | * @param <T> ç®æ å¯¹è±¡çæ³åç±»å |
| | | * @return 转æ¢åç对象ï¼å¦æå符串为空åè¿ånull |
| | | * @throws RuntimeException å¦æè½¬æ¢è¿ç¨ä¸åçIOå¼å¸¸ï¼åæåºè¿è¡æ¶å¼å¸¸ |
| | | */ |
| | | public static <T> T parseObject(String text, Class<T> clazz) { |
| | | if (StringUtils.isEmpty(text)) { |
| | | return null; |
| | | } |
| | | try { |
| | | return OBJECT_MAPPER.readValue(text, clazz); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°åèæ°ç»è½¬æ¢ä¸ºæå®ç±»åç对象 |
| | | * |
| | | * @param bytes åèæ°ç» |
| | | * @param clazz è¦è½¬æ¢çç®æ 对象类å |
| | | * @param <T> ç®æ å¯¹è±¡çæ³åç±»å |
| | | * @return 转æ¢åç对象ï¼å¦æåèæ°ç»ä¸ºç©ºåè¿ånull |
| | | * @throws RuntimeException å¦æè½¬æ¢è¿ç¨ä¸åçIOå¼å¸¸ï¼åæåºè¿è¡æ¶å¼å¸¸ |
| | | */ |
| | | public static <T> T parseObject(byte[] bytes, Class<T> clazz) { |
| | | if (ArrayUtil.isEmpty(bytes)) { |
| | | return null; |
| | | } |
| | | try { |
| | | return OBJECT_MAPPER.readValue(bytes, clazz); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°JSONæ ¼å¼çå符串转æ¢ä¸ºæå®ç±»åçå¯¹è±¡ï¼æ¯æå¤æç±»å |
| | | * |
| | | * @param text JSONæ ¼å¼çå符串 |
| | | * @param typeReference æå®ç±»åçTypeReference对象 |
| | | * @param <T> ç®æ å¯¹è±¡çæ³åç±»å |
| | | * @return 转æ¢åç对象ï¼å¦æå符串为空åè¿ånull |
| | | * @throws RuntimeException å¦æè½¬æ¢è¿ç¨ä¸åçIOå¼å¸¸ï¼åæåºè¿è¡æ¶å¼å¸¸ |
| | | */ |
| | | public static <T> T parseObject(String text, TypeReference<T> typeReference) { |
| | | if (StringUtils.isBlank(text)) { |
| | | return null; |
| | | } |
| | | try { |
| | | return OBJECT_MAPPER.readValue(text, typeReference); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°JSONæ ¼å¼çå符串转æ¢ä¸ºDict对象 |
| | | * |
| | | * @param text JSONæ ¼å¼çå符串 |
| | | * @return 转æ¢åçDict对象ï¼å¦æå符串为空æè
䏿¯JSONæ ¼å¼åè¿ånull |
| | | * @throws RuntimeException å¦æè½¬æ¢è¿ç¨ä¸åçIOå¼å¸¸ï¼åæåºè¿è¡æ¶å¼å¸¸ |
| | | */ |
| | | public static Dict parseMap(String text) { |
| | | if (StringUtils.isBlank(text)) { |
| | | return null; |
| | | } |
| | | try { |
| | | return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructType(Dict.class)); |
| | | } catch (MismatchedInputException e) { |
| | | // ç±»åä¸å¹é
说æä¸æ¯json |
| | | return null; |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°JSONæ ¼å¼çå符串转æ¢ä¸ºDict对象çå表 |
| | | * |
| | | * @param text JSONæ ¼å¼çå符串 |
| | | * @return 转æ¢åçDict对象çå表ï¼å¦æå符串为空åè¿ånull |
| | | * @throws RuntimeException å¦æè½¬æ¢è¿ç¨ä¸åçIOå¼å¸¸ï¼åæåºè¿è¡æ¶å¼å¸¸ |
| | | */ |
| | | public static List<Dict> parseArrayMap(String text) { |
| | | if (StringUtils.isBlank(text)) { |
| | | return null; |
| | | } |
| | | try { |
| | | return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, Dict.class)); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å°JSONæ ¼å¼çå符串转æ¢ä¸ºæå®ç±»å对象çå表 |
| | | * |
| | | * @param text JSONæ ¼å¼çå符串 |
| | | * @param clazz è¦è½¬æ¢çç®æ 对象类å |
| | | * @param <T> ç®æ å¯¹è±¡çæ³åç±»å |
| | | * @return 转æ¢åç对象çå表ï¼å¦æå符串为空åè¿å空å表 |
| | | * @throws RuntimeException å¦æè½¬æ¢è¿ç¨ä¸åçIOå¼å¸¸ï¼åæåºè¿è¡æ¶å¼å¸¸ |
| | | */ |
| | | public static <T> List<T> parseArray(String text, Class<T> clazz) { |
| | | if (StringUtils.isEmpty(text)) { |
| | | return new ArrayList<>(); |
| | | } |
| | | try { |
| | | return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, clazz)); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 夿å符串æ¯å¦ä¸ºåæ³ JSONï¼å¯¹è±¡ææ°ç»ï¼ |
| | | * |
| | | * @param str å¾
æ ¡éªå符串 |
| | | * @return true = åæ³ JSONï¼false = éæ³æç©º |
| | | */ |
| | | public static boolean isJson(String str) { |
| | | if (StringUtils.isBlank(str)) { |
| | | return false; |
| | | } |
| | | try { |
| | | OBJECT_MAPPER.readTree(str); |
| | | return true; |
| | | } catch (Exception e) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 夿å符串æ¯å¦ä¸º JSON 对象ï¼{}ï¼ |
| | | * |
| | | * @param str å¾
æ ¡éªå符串 |
| | | * @return true = JSON 对象 |
| | | */ |
| | | public static boolean isJsonObject(String str) { |
| | | if (StringUtils.isBlank(str)) { |
| | | return false; |
| | | } |
| | | try { |
| | | JsonNode node = OBJECT_MAPPER.readTree(str); |
| | | return node.isObject(); |
| | | } catch (Exception e) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 夿å符串æ¯å¦ä¸º JSON æ°ç»ï¼[]ï¼ |
| | | * |
| | | * @param str å¾
æ ¡éªå符串 |
| | | * @return true = JSON æ°ç» |
| | | */ |
| | | public static boolean isJsonArray(String str) { |
| | | if (StringUtils.isBlank(str)) { |
| | | return false; |
| | | } |
| | | try { |
| | | JsonNode node = OBJECT_MAPPER.readTree(str); |
| | | return node.isArray(); |
| | | } catch (Exception e) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.json.validate; |
| | | |
| | | import jakarta.validation.Constraint; |
| | | import jakarta.validation.Payload; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * JSON æ ¼å¼æ ¡éªæ³¨è§£ |
| | | * |
| | | * @author AprilWind |
| | | */ |
| | | @Documented |
| | | @Target({ElementType.METHOD, ElementType.FIELD}) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @Constraint(validatedBy = JsonPatternValidator.class) |
| | | public @interface JsonPattern { |
| | | |
| | | /** |
| | | * éå¶ JSON ç±»åï¼é»è®¤ä¸º {@link JsonType#ANY}ï¼å³å¯¹è±¡ææ°ç»é½å
许 |
| | | */ |
| | | JsonType type() default JsonType.ANY; |
| | | |
| | | /** |
| | | * æ ¡éªå¤±è´¥æ¶çæç¤ºæ¶æ¯ |
| | | */ |
| | | String message() default "䏿¯ææç JSON æ ¼å¼"; |
| | | |
| | | Class<?>[] groups() default {}; |
| | | |
| | | Class<? extends Payload>[] payload() default {}; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.json.validate; |
| | | |
| | | import jakarta.validation.ConstraintValidator; |
| | | import jakarta.validation.ConstraintValidatorContext; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.json.utils.JsonUtils; |
| | | |
| | | /** |
| | | * JSON æ ¼å¼æ ¡éªå¨ |
| | | * |
| | | * @author AprilWind |
| | | */ |
| | | public class JsonPatternValidator implements ConstraintValidator<JsonPattern, String> { |
| | | |
| | | /** |
| | | * æ³¨è§£ä¸æå®ç JSON ç±»åæä¸¾ |
| | | */ |
| | | private JsonType jsonType; |
| | | |
| | | /** |
| | | * åå§åæ ¡éªå¨ï¼ä»æ³¨è§£ä¸æå JSON ç±»å |
| | | * |
| | | * @param annotation 注解å®ä¾ |
| | | */ |
| | | @Override |
| | | public void initialize(JsonPattern annotation) { |
| | | this.jsonType = annotation.type(); |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªå符串æ¯å¦ä¸ºåæ³ JSON |
| | | * |
| | | * @param value å¾
æ ¡éªå符串 |
| | | * @param context æ ¡éªä¸ä¸æï¼å¯ç¨äºèªå®ä¹éè¯¯ä¿¡æ¯ |
| | | * @return true = åæ³ JSON æä¸ºç©ºï¼false = éæ³ JSON |
| | | */ |
| | | @Override |
| | | public boolean isValid(String value, ConstraintValidatorContext context) { |
| | | if (StringUtils.isBlank(value)) { |
| | | // äº¤ç» @NotBlank æ @NotNull æ§å¶æ¯å¦å
许为空 |
| | | return true; |
| | | } |
| | | // æ ¹æ® JSON ç±»åè¿è¡ä¸åçæ ¡éª |
| | | return switch (jsonType) { |
| | | case ANY -> JsonUtils.isJson(value); |
| | | case OBJECT -> JsonUtils.isJsonObject(value); |
| | | case ARRAY -> JsonUtils.isJsonArray(value); |
| | | }; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.json.validate; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | |
| | | /** |
| | | * JSON ç±»åæä¸¾ |
| | | * |
| | | * @author AprilWind |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum JsonType { |
| | | |
| | | /** |
| | | * JSON 对象ï¼ä¾å¦ {"a":1} |
| | | */ |
| | | OBJECT, |
| | | |
| | | /** |
| | | * JSON æ°ç»ï¼ä¾å¦ [1,2,3] |
| | | */ |
| | | ARRAY, |
| | | |
| | | /** |
| | | * ä»»æ JSON ç±»åï¼å¯¹è±¡ææ°ç»é½å¯ä»¥ |
| | | */ |
| | | ANY |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | org.dromara.common.json.config.JacksonConfig |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>5.5.3</version> |
| | | </parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-log</artifactId> |
| | | <version>5.5.3</version> |
| | | <description>ruoyi-common-log æ¥å¿è®°å½</description> |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-satoken</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-json</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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"> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>${revision}</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>ruoyi-common-log</artifactId> |
| | | |
| | | <description> |
| | | ruoyi-common-log æ¥å¿è®°å½ |
| | | </description> |
| | | |
| | | <dependencies> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-satoken</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-json</artifactId> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.log.annotation; |
| | | |
| | | import org.dromara.common.log.enums.BusinessType; |
| | | import org.dromara.common.log.enums.OperatorType; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * èªå®ä¹æä½æ¥å¿è®°å½æ³¨è§£ |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | @Target({ElementType.PARAMETER, ElementType.METHOD}) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @Documented |
| | | public @interface Log { |
| | | /** |
| | | * 模å |
| | | */ |
| | | String title() default ""; |
| | | |
| | | /** |
| | | * åè½ |
| | | */ |
| | | BusinessType businessType() default BusinessType.OTHER; |
| | | |
| | | /** |
| | | * æä½äººç±»å« |
| | | */ |
| | | OperatorType operatorType() default OperatorType.MANAGE; |
| | | |
| | | /** |
| | | * æ¯å¦ä¿å请æ±çåæ° |
| | | */ |
| | | boolean isSaveRequestData() default true; |
| | | |
| | | /** |
| | | * æ¯å¦ä¿åååºçåæ° |
| | | */ |
| | | boolean isSaveResponseData() default true; |
| | | |
| | | |
| | | /** |
| | | * æé¤æå®ç请æ±åæ° |
| | | */ |
| | | String[] excludeParamNames() default {}; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.log.aspect; |
| | | |
| | | import cn.hutool.core.lang.Dict; |
| | | import cn.hutool.core.map.MapUtil; |
| | | import cn.hutool.core.util.ArrayUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.time.StopWatch; |
| | | import org.aspectj.lang.JoinPoint; |
| | | import org.aspectj.lang.annotation.AfterReturning; |
| | | import org.aspectj.lang.annotation.AfterThrowing; |
| | | import org.aspectj.lang.annotation.Aspect; |
| | | import org.aspectj.lang.annotation.Before; |
| | | import org.dromara.common.core.constant.SystemConstants; |
| | | import org.dromara.common.core.domain.model.LoginUser; |
| | | import org.dromara.common.core.utils.ServletUtils; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.json.utils.JsonUtils; |
| | | import org.dromara.common.log.annotation.Log; |
| | | import org.dromara.common.log.enums.BusinessStatus; |
| | | import org.dromara.common.log.event.OperLogEvent; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.http.HttpMethod; |
| | | import org.springframework.validation.BindingResult; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.util.*; |
| | | |
| | | /** |
| | | * æä½æ¥å¿è®°å½å¤ç |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Slf4j |
| | | @Aspect |
| | | @AutoConfiguration |
| | | public class LogAspect { |
| | | |
| | | /** |
| | | * è®¡æ¶ key |
| | | */ |
| | | private static final ThreadLocal<StopWatch> KEY_CACHE = new ThreadLocal<>(); |
| | | |
| | | /** |
| | | * å¤ç请æ±åæ§è¡ |
| | | */ |
| | | @Before(value = "@annotation(controllerLog)") |
| | | public void doBefore(JoinPoint joinPoint, Log controllerLog) { |
| | | StopWatch stopWatch = new StopWatch(); |
| | | KEY_CACHE.set(stopWatch); |
| | | stopWatch.start(); |
| | | } |
| | | |
| | | /** |
| | | * å¤çå®è¯·æ±åæ§è¡ |
| | | * |
| | | * @param joinPoint åç¹ |
| | | */ |
| | | @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult") |
| | | public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) { |
| | | handleLog(joinPoint, controllerLog, null, jsonResult); |
| | | } |
| | | |
| | | /** |
| | | * æ¦æªå¼å¸¸æä½ |
| | | * |
| | | * @param joinPoint åç¹ |
| | | * @param e å¼å¸¸ |
| | | */ |
| | | @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e") |
| | | public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) { |
| | | handleLog(joinPoint, controllerLog, e, null); |
| | | } |
| | | |
| | | protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) { |
| | | try { |
| | | |
| | | // *========æ°æ®åºæ¥å¿=========*// |
| | | OperLogEvent operLog = new OperLogEvent(); |
| | | operLog.setTenantId(LoginHelper.getTenantId()); |
| | | operLog.setStatus(BusinessStatus.SUCCESS.ordinal()); |
| | | // 请æ±çå°å |
| | | String ip = ServletUtils.getClientIP(); |
| | | operLog.setOperIp(ip); |
| | | operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255)); |
| | | LoginUser loginUser = LoginHelper.getLoginUser(); |
| | | operLog.setOperName(loginUser.getUsername()); |
| | | operLog.setDeptName(loginUser.getDeptName()); |
| | | |
| | | if (e != null) { |
| | | operLog.setStatus(BusinessStatus.FAIL.ordinal()); |
| | | operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 3800)); |
| | | } |
| | | // è®¾ç½®æ¹æ³åç§° |
| | | String className = joinPoint.getTarget().getClass().getName(); |
| | | String methodName = joinPoint.getSignature().getName(); |
| | | operLog.setMethod(className + "." + methodName + "()"); |
| | | // è®¾ç½®è¯·æ±æ¹å¼ |
| | | operLog.setRequestMethod(ServletUtils.getRequest().getMethod()); |
| | | // å¤ç设置注解ä¸çåæ° |
| | | getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult); |
| | | // 设置æ¶èæ¶é´ |
| | | StopWatch stopWatch = KEY_CACHE.get(); |
| | | stopWatch.stop(); |
| | | operLog.setCostTime(stopWatch.getDuration().toMillis()); |
| | | // åå¸äºä»¶ä¿åæ°æ®åº |
| | | SpringUtils.context().publishEvent(operLog); |
| | | } catch (Exception exp) { |
| | | // è®°å½æ¬å°å¼å¸¸æ¥å¿ |
| | | log.error("å¼å¸¸ä¿¡æ¯:{}", exp.getMessage()); |
| | | } finally { |
| | | KEY_CACHE.remove(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è·å注解ä¸å¯¹æ¹æ³çæè¿°ä¿¡æ¯ ç¨äºController屿³¨è§£ |
| | | * |
| | | * @param log æ¥å¿ |
| | | * @param operLog æä½æ¥å¿ |
| | | * @throws Exception |
| | | */ |
| | | public void getControllerMethodDescription(JoinPoint joinPoint, Log log, OperLogEvent operLog, Object jsonResult) throws Exception { |
| | | // 设置actionå¨ä½ |
| | | operLog.setBusinessType(log.businessType().ordinal()); |
| | | // 设置æ é¢ |
| | | operLog.setTitle(log.title()); |
| | | // 设置æä½äººç±»å« |
| | | operLog.setOperatorType(log.operatorType().ordinal()); |
| | | // æ¯å¦éè¦ä¿årequestï¼åæ°åå¼ |
| | | if (log.isSaveRequestData()) { |
| | | // è·ååæ°çä¿¡æ¯ï¼ä¼ å
¥å°æ°æ®åºä¸ã |
| | | setRequestValue(joinPoint, operLog, log.excludeParamNames()); |
| | | } |
| | | // æ¯å¦éè¦ä¿åresponseï¼åæ°åå¼ |
| | | if (log.isSaveResponseData() && ObjectUtil.isNotNull(jsonResult)) { |
| | | operLog.setJsonResult(StringUtils.substring(JsonUtils.toJsonString(jsonResult), 0, 3800)); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è·å请æ±çåæ°ï¼æ¾å°logä¸ |
| | | * |
| | | * @param operLog æä½æ¥å¿ |
| | | * @throws Exception å¼å¸¸ |
| | | */ |
| | | private void setRequestValue(JoinPoint joinPoint, OperLogEvent operLog, String[] excludeParamNames) throws Exception { |
| | | Map<String, String> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest()); |
| | | String requestMethod = operLog.getRequestMethod(); |
| | | if (MapUtil.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name())) { |
| | | String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames); |
| | | operLog.setOperParam(StringUtils.substring(params, 0, 3800)); |
| | | } else { |
| | | MapUtil.removeAny(paramsMap, SystemConstants.EXCLUDE_PROPERTIES); |
| | | MapUtil.removeAny(paramsMap, excludeParamNames); |
| | | operLog.setOperParam(StringUtils.substring(JsonUtils.toJsonString(paramsMap), 0, 3800)); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * åæ°æ¼è£
|
| | | */ |
| | | private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames) { |
| | | StringJoiner params = new StringJoiner(" "); |
| | | if (ArrayUtil.isEmpty(paramsArray)) { |
| | | return params.toString(); |
| | | } |
| | | String[] exclude = ArrayUtil.addAll(excludeParamNames, SystemConstants.EXCLUDE_PROPERTIES); |
| | | for (Object o : paramsArray) { |
| | | if (ObjectUtil.isNotNull(o) && !isFilterObject(o)) { |
| | | String str = ""; |
| | | if (o instanceof List<?> list) { |
| | | List<Dict> list1 = new ArrayList<>(); |
| | | for (Object obj : list) { |
| | | String str1 = JsonUtils.toJsonString(obj); |
| | | Dict dict = JsonUtils.parseMap(str1); |
| | | if (MapUtil.isNotEmpty(dict)) { |
| | | MapUtil.removeAny(dict, exclude); |
| | | list1.add(dict); |
| | | } |
| | | } |
| | | str = JsonUtils.toJsonString(list1); |
| | | } else { |
| | | str = JsonUtils.toJsonString(o); |
| | | Dict dict = JsonUtils.parseMap(str); |
| | | if (MapUtil.isNotEmpty(dict)) { |
| | | MapUtil.removeAny(dict, exclude); |
| | | str = JsonUtils.toJsonString(dict); |
| | | } |
| | | } |
| | | params.add(str); |
| | | } |
| | | } |
| | | return params.toString(); |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦éè¦è¿æ»¤ç对象ã |
| | | * |
| | | * @param o 对象信æ¯ã |
| | | * @return 妿æ¯éè¦è¿æ»¤ç对象ï¼åè¿åtrueï¼å¦åè¿åfalseã |
| | | */ |
| | | @SuppressWarnings("rawtypes") |
| | | public boolean isFilterObject(final Object o) { |
| | | Class<?> clazz = o.getClass(); |
| | | if (clazz.isArray()) { |
| | | return MultipartFile.class.isAssignableFrom(clazz.getComponentType()); |
| | | } else if (Collection.class.isAssignableFrom(clazz)) { |
| | | Collection collection = (Collection) o; |
| | | for (Object value : collection) { |
| | | return value instanceof MultipartFile; |
| | | } |
| | | } else if (Map.class.isAssignableFrom(clazz)) { |
| | | Map map = (Map) o; |
| | | for (Object value : map.values()) { |
| | | return value instanceof MultipartFile; |
| | | } |
| | | } |
| | | return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse |
| | | || o instanceof BindingResult; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.log.enums; |
| | | |
| | | /** |
| | | * æä½ç¶æ |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | public enum BusinessStatus { |
| | | /** |
| | | * æå |
| | | */ |
| | | SUCCESS, |
| | | |
| | | /** |
| | | * 失败 |
| | | */ |
| | | FAIL, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.log.enums; |
| | | |
| | | /** |
| | | * ä¸å¡æä½ç±»å |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | public enum BusinessType { |
| | | /** |
| | | * å
¶å® |
| | | */ |
| | | OTHER, |
| | | |
| | | /** |
| | | * æ°å¢ |
| | | */ |
| | | INSERT, |
| | | |
| | | /** |
| | | * ä¿®æ¹ |
| | | */ |
| | | UPDATE, |
| | | |
| | | /** |
| | | * å é¤ |
| | | */ |
| | | DELETE, |
| | | |
| | | /** |
| | | * ææ |
| | | */ |
| | | GRANT, |
| | | |
| | | /** |
| | | * å¯¼åº |
| | | */ |
| | | EXPORT, |
| | | |
| | | /** |
| | | * 导å
¥ |
| | | */ |
| | | IMPORT, |
| | | |
| | | /** |
| | | * 强é |
| | | */ |
| | | FORCE, |
| | | |
| | | /** |
| | | * çæä»£ç |
| | | */ |
| | | GENCODE, |
| | | |
| | | /** |
| | | * æ¸
ç©ºæ°æ® |
| | | */ |
| | | CLEAN, |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.log.enums; |
| | | |
| | | /** |
| | | * æä½äººç±»å« |
| | | * |
| | | * @author ruoyi |
| | | */ |
| | | public enum OperatorType { |
| | | /** |
| | | * å
¶å® |
| | | */ |
| | | OTHER, |
| | | |
| | | /** |
| | | * åå°ç¨æ· |
| | | */ |
| | | MANAGE, |
| | | |
| | | /** |
| | | * ææºç«¯ç¨æ· |
| | | */ |
| | | MOBILE |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.log.event; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * ç»å½äºä»¶ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | |
| | | @Data |
| | | public class LogininforEvent implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * ç§æ·ID |
| | | */ |
| | | private String tenantId; |
| | | |
| | | /** |
| | | * ç¨æ·è´¦å· |
| | | */ |
| | | private String username; |
| | | |
| | | /** |
| | | * ç»å½ç¶æ 0æå 1失败 |
| | | */ |
| | | private String status; |
| | | |
| | | /** |
| | | * æç¤ºæ¶æ¯ |
| | | */ |
| | | private String message; |
| | | |
| | | /** |
| | | * 请æ±ä½ |
| | | */ |
| | | private HttpServletRequest request; |
| | | |
| | | /** |
| | | * å
¶ä»åæ° |
| | | */ |
| | | private Object[] args; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.log.event; |
| | | |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * æä½æ¥å¿äºä»¶ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | |
| | | @Data |
| | | public class OperLogEvent implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * æ¥å¿ä¸»é® |
| | | */ |
| | | private Long operId; |
| | | |
| | | /** |
| | | * ç§æ·ID |
| | | */ |
| | | private String tenantId; |
| | | |
| | | /** |
| | | * æä½æ¨¡å |
| | | */ |
| | | private String title; |
| | | |
| | | /** |
| | | * ä¸å¡ç±»åï¼0å
¶å® 1æ°å¢ 2ä¿®æ¹ 3å é¤ï¼ |
| | | */ |
| | | private Integer businessType; |
| | | |
| | | /** |
| | | * ä¸å¡ç±»åæ°ç» |
| | | */ |
| | | private Integer[] businessTypes; |
| | | |
| | | /** |
| | | * è¯·æ±æ¹æ³ |
| | | */ |
| | | private String method; |
| | | |
| | | /** |
| | | * è¯·æ±æ¹å¼ |
| | | */ |
| | | private String requestMethod; |
| | | |
| | | /** |
| | | * æä½ç±»å«ï¼0å
¶å® 1åå°ç¨æ· 2ææºç«¯ç¨æ·ï¼ |
| | | */ |
| | | private Integer operatorType; |
| | | |
| | | /** |
| | | * æä½äººå |
| | | */ |
| | | private String operName; |
| | | |
| | | /** |
| | | * é¨é¨åç§° |
| | | */ |
| | | private String deptName; |
| | | |
| | | /** |
| | | * 请æ±url |
| | | */ |
| | | private String operUrl; |
| | | |
| | | /** |
| | | * æä½å°å |
| | | */ |
| | | private String operIp; |
| | | |
| | | /** |
| | | * æä½å°ç¹ |
| | | */ |
| | | private String operLocation; |
| | | |
| | | /** |
| | | * 请æ±åæ° |
| | | */ |
| | | private String operParam; |
| | | |
| | | /** |
| | | * è¿ååæ° |
| | | */ |
| | | private String jsonResult; |
| | | |
| | | /** |
| | | * æä½ç¶æï¼0æ£å¸¸ 1å¼å¸¸ï¼ |
| | | */ |
| | | private Integer status; |
| | | |
| | | /** |
| | | * éè¯¯æ¶æ¯ |
| | | */ |
| | | private String errorMsg; |
| | | |
| | | /** |
| | | * æä½æ¶é´ |
| | | */ |
| | | private Date operTime; |
| | | |
| | | /** |
| | | * æ¶èæ¶é´ |
| | | */ |
| | | private Long costTime; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | org.dromara.common.log.aspect.LogAspect |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>5.5.3</version> |
| | | </parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-mail</artifactId> |
| | | <version>5.5.3</version> |
| | | <description>ruoyi-common-mail é®ä»¶æ¨¡å</description> |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>jakarta.mail</groupId> |
| | | <artifactId>jakarta.mail-api</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.eclipse.angus</groupId> |
| | | <artifactId>jakarta.mail</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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"> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>${revision}</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>ruoyi-common-mail</artifactId> |
| | | |
| | | <description> |
| | | ruoyi-common-mail é®ä»¶æ¨¡å |
| | | </description> |
| | | |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>jakarta.mail</groupId> |
| | | <artifactId>jakarta.mail-api</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.eclipse.angus</groupId> |
| | | <artifactId>jakarta.mail</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.mail.config; |
| | | |
| | | import cn.hutool.extra.mail.MailAccount; |
| | | import org.dromara.common.mail.config.properties.MailProperties; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| | | import org.springframework.context.annotation.Bean; |
| | | |
| | | /** |
| | | * JavaMail é
ç½® |
| | | * |
| | | * @author Michelle.Chung |
| | | */ |
| | | @AutoConfiguration |
| | | @EnableConfigurationProperties(MailProperties.class) |
| | | public class MailConfig { |
| | | |
| | | @Bean |
| | | @ConditionalOnProperty(value = "mail.enabled", havingValue = "true") |
| | | public MailAccount mailAccount(MailProperties mailProperties) { |
| | | MailAccount account = new MailAccount(); |
| | | account.setHost(mailProperties.getHost()); |
| | | account.setPort(mailProperties.getPort()); |
| | | account.setAuth(mailProperties.getAuth()); |
| | | account.setFrom(mailProperties.getFrom()); |
| | | account.setUser(mailProperties.getUser()); |
| | | account.setPass(mailProperties.getPass()); |
| | | account.setSocketFactoryPort(mailProperties.getPort()); |
| | | account.setStarttlsEnable(mailProperties.getStarttlsEnable()); |
| | | account.setSslEnable(mailProperties.getSslEnable()); |
| | | account.setTimeout(mailProperties.getTimeout()); |
| | | account.setConnectionTimeout(mailProperties.getConnectionTimeout()); |
| | | return account; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.mail.config.properties; |
| | | |
| | | import lombok.Data; |
| | | import org.springframework.boot.context.properties.ConfigurationProperties; |
| | | |
| | | /** |
| | | * JavaMail é
ç½®å±æ§ |
| | | * |
| | | * @author Michelle.Chung |
| | | */ |
| | | @Data |
| | | @ConfigurationProperties(prefix = "mail") |
| | | public class MailProperties { |
| | | |
| | | /** |
| | | * è¿æ»¤å¼å
³ |
| | | */ |
| | | private Boolean enabled; |
| | | |
| | | /** |
| | | * SMTPæå¡å¨åå |
| | | */ |
| | | private String host; |
| | | |
| | | /** |
| | | * SMTPæå¡ç«¯å£ |
| | | */ |
| | | private Integer port; |
| | | |
| | | /** |
| | | * æ¯å¦éè¦ç¨æ·åå¯ç éªè¯ |
| | | */ |
| | | private Boolean auth; |
| | | |
| | | /** |
| | | * ç¨æ·å |
| | | */ |
| | | private String user; |
| | | |
| | | /** |
| | | * å¯ç |
| | | */ |
| | | private String pass; |
| | | |
| | | /** |
| | | * åéæ¹ï¼éµå¾ªRFC-822æ å<br> |
| | | * å件人å¯ä»¥æ¯ä»¥ä¸å½¢å¼ï¼ |
| | | * |
| | | * <pre> |
| | | * 1. user@xxx.xx |
| | | * 2. name <user@xxx.xx> |
| | | * </pre> |
| | | */ |
| | | private String from; |
| | | |
| | | /** |
| | | * ä½¿ç¨ STARTTLSå®å
¨è¿æ¥ï¼STARTTLSæ¯å¯¹çº¯ææ¬éä¿¡åè®®çæ©å±ãå®å°çº¯ææ¬è¿æ¥å级为å å¯è¿æ¥ï¼TLSæSSLï¼ï¼ è䏿¯ä½¿ç¨ä¸ä¸ªåç¬çå å¯é信端å£ã |
| | | */ |
| | | private Boolean starttlsEnable; |
| | | |
| | | /** |
| | | * ä½¿ç¨ SSLå®å
¨è¿æ¥ |
| | | */ |
| | | private Boolean sslEnable; |
| | | |
| | | /** |
| | | * SMTPè¶
æ¶æ¶é¿ï¼å使¯«ç§ï¼ç¼ºçå¼ä¸è¶
æ¶ |
| | | */ |
| | | private Long timeout; |
| | | |
| | | /** |
| | | * Socketè¿æ¥è¶
æ¶å¼ï¼å使¯«ç§ï¼ç¼ºçå¼ä¸è¶
æ¶ |
| | | */ |
| | | private Long connectionTimeout; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.mail.utils; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.io.IoUtil; |
| | | import cn.hutool.core.map.MapUtil; |
| | | import cn.hutool.core.util.CharUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.hutool.extra.mail.JakartaMail; |
| | | import cn.hutool.extra.mail.JakartaUserPassAuthenticator; |
| | | import cn.hutool.extra.mail.MailAccount; |
| | | import jakarta.mail.Authenticator; |
| | | import jakarta.mail.Session; |
| | | import lombok.AccessLevel; |
| | | import lombok.NoArgsConstructor; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | |
| | | import java.io.File; |
| | | import java.io.InputStream; |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Map.Entry; |
| | | |
| | | /** |
| | | * é®ä»¶å·¥å
·ç±» |
| | | */ |
| | | @NoArgsConstructor(access = AccessLevel.PRIVATE) |
| | | public class MailUtils { |
| | | |
| | | private static final MailAccount ACCOUNT = SpringUtils.getBean(MailAccount.class); |
| | | |
| | | /** |
| | | * è·åé®ä»¶åéå®ä¾ |
| | | */ |
| | | public static MailAccount getMailAccount() { |
| | | return ACCOUNT; |
| | | } |
| | | |
| | | /** |
| | | * è·åé®ä»¶åéå®ä¾ (èªå®ä¹åéäººä»¥åææç ) |
| | | * |
| | | * @param user åé人 |
| | | * @param pass ææç |
| | | */ |
| | | public static MailAccount getMailAccount(String from, String user, String pass) { |
| | | ACCOUNT.setFrom(StringUtils.blankToDefault(from, ACCOUNT.getFrom())); |
| | | ACCOUNT.setUser(StringUtils.blankToDefault(user, ACCOUNT.getUser())); |
| | | ACCOUNT.setPass(StringUtils.blankToDefault(pass, ACCOUNT.getPass())); |
| | | return ACCOUNT; |
| | | } |
| | | |
| | | /** |
| | | * 使ç¨é
ç½®æä»¶ä¸è®¾ç½®çè´¦æ·åéææ¬é®ä»¶ï¼åéç»å个æå¤ä¸ªæ¶ä»¶äºº<br> |
| | | * å¤ä¸ªæ¶ä»¶äººå¯ä»¥ä½¿ç¨éå·â,âåéï¼ä¹å¯ä»¥éè¿åå·â;âåé |
| | | * |
| | | * @param to æ¶ä»¶äºº |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | * @since 3.2.0 |
| | | */ |
| | | public static String sendText(String to, String subject, String content, File... files) { |
| | | return send(to, subject, content, false, files); |
| | | } |
| | | |
| | | /** |
| | | * 使ç¨é
ç½®æä»¶ä¸è®¾ç½®çè´¦æ·åéHTMLé®ä»¶ï¼åéç»å个æå¤ä¸ªæ¶ä»¶äºº<br> |
| | | * å¤ä¸ªæ¶ä»¶äººå¯ä»¥ä½¿ç¨éå·â,âåéï¼ä¹å¯ä»¥éè¿åå·â;âåé |
| | | * |
| | | * @param to æ¶ä»¶äºº |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | * @since 3.2.0 |
| | | */ |
| | | public static String sendHtml(String to, String subject, String content, File... files) { |
| | | return send(to, subject, content, true, files); |
| | | } |
| | | |
| | | /** |
| | | * 使ç¨é
ç½®æä»¶ä¸è®¾ç½®çè´¦æ·åéé®ä»¶ï¼åéå个æå¤ä¸ªæ¶ä»¶äºº<br> |
| | | * å¤ä¸ªæ¶ä»¶äººå¯ä»¥ä½¿ç¨éå·â,âåéï¼ä¹å¯ä»¥éè¿åå·â;âåé |
| | | * |
| | | * @param to æ¶ä»¶äºº |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param isHtml æ¯å¦ä¸ºHTML |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | */ |
| | | public static String send(String to, String subject, String content, boolean isHtml, File... files) { |
| | | return send(splitAddress(to), subject, content, isHtml, files); |
| | | } |
| | | |
| | | /** |
| | | * 使ç¨é
ç½®æä»¶ä¸è®¾ç½®çè´¦æ·åéé®ä»¶ï¼åéå个æå¤ä¸ªæ¶ä»¶äºº<br> |
| | | * å¤ä¸ªæ¶ä»¶äººãæé人ãå¯é人å¯ä»¥ä½¿ç¨éå·â,âåéï¼ä¹å¯ä»¥éè¿åå·â;âåé |
| | | * |
| | | * @param to æ¶ä»¶äººï¼å¯ä»¥ä½¿ç¨éå·â,âåéï¼ä¹å¯ä»¥éè¿åå·â;âåé |
| | | * @param cc æé人ï¼å¯ä»¥ä½¿ç¨éå·â,âåéï¼ä¹å¯ä»¥éè¿åå·â;âåé |
| | | * @param bcc å¯é人ï¼å¯ä»¥ä½¿ç¨éå·â,âåéï¼ä¹å¯ä»¥éè¿åå·â;âåé |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param isHtml æ¯å¦ä¸ºHTML |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | * @since 4.0.3 |
| | | */ |
| | | public static String send(String to, String cc, String bcc, String subject, String content, boolean isHtml, File... files) { |
| | | return send(splitAddress(to), splitAddress(cc), splitAddress(bcc), subject, content, isHtml, files); |
| | | } |
| | | |
| | | /** |
| | | * 使ç¨é
ç½®æä»¶ä¸è®¾ç½®çè´¦æ·åéææ¬é®ä»¶ï¼åéç»å¤äºº |
| | | * |
| | | * @param tos æ¶ä»¶äººå表 |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | */ |
| | | public static String sendText(Collection<String> tos, String subject, String content, File... files) { |
| | | return send(tos, subject, content, false, files); |
| | | } |
| | | |
| | | /** |
| | | * 使ç¨é
ç½®æä»¶ä¸è®¾ç½®çè´¦æ·åéHTMLé®ä»¶ï¼åéç»å¤äºº |
| | | * |
| | | * @param tos æ¶ä»¶äººå表 |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | * @since 3.2.0 |
| | | */ |
| | | public static String sendHtml(Collection<String> tos, String subject, String content, File... files) { |
| | | return send(tos, subject, content, true, files); |
| | | } |
| | | |
| | | /** |
| | | * 使ç¨é
ç½®æä»¶ä¸è®¾ç½®çè´¦æ·åéé®ä»¶ï¼åéç»å¤äºº |
| | | * |
| | | * @param tos æ¶ä»¶äººå表 |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param isHtml æ¯å¦ä¸ºHTML |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | */ |
| | | public static String send(Collection<String> tos, String subject, String content, boolean isHtml, File... files) { |
| | | return send(tos, null, null, subject, content, isHtml, files); |
| | | } |
| | | |
| | | /** |
| | | * 使ç¨é
ç½®æä»¶ä¸è®¾ç½®çè´¦æ·åéé®ä»¶ï¼åéç»å¤äºº |
| | | * |
| | | * @param tos æ¶ä»¶äººå表 |
| | | * @param ccs æé人å表ï¼å¯ä»¥ä¸ºnullæç©º |
| | | * @param bccs å¯é人å表ï¼å¯ä»¥ä¸ºnullæç©º |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param isHtml æ¯å¦ä¸ºHTML |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | * @since 4.0.3 |
| | | */ |
| | | public static String send(Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, boolean isHtml, File... files) { |
| | | return send(getMailAccount(), true, tos, ccs, bccs, subject, content, null, isHtml, files); |
| | | } |
| | | |
| | | // ------------------------------------------------------------------------------------------------------------------------------- Custom MailAccount |
| | | |
| | | /** |
| | | * åéé®ä»¶ç»å¤äºº |
| | | * |
| | | * @param mailAccount é®ä»¶è®¤è¯å¯¹è±¡ |
| | | * @param to æ¶ä»¶äººï¼å¤ä¸ªæ¶ä»¶äººéå·æè
åå·éå¼ |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param isHtml æ¯å¦ä¸ºHTMLæ ¼å¼ |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | * @since 3.2.0 |
| | | */ |
| | | public static String send(MailAccount mailAccount, String to, String subject, String content, boolean isHtml, File... files) { |
| | | return send(mailAccount, splitAddress(to), subject, content, isHtml, files); |
| | | } |
| | | |
| | | /** |
| | | * åéé®ä»¶ç»å¤äºº |
| | | * |
| | | * @param mailAccount é®ä»¶è´¦æ·ä¿¡æ¯ |
| | | * @param tos æ¶ä»¶äººå表 |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param isHtml æ¯å¦ä¸ºHTMLæ ¼å¼ |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | */ |
| | | public static String send(MailAccount mailAccount, Collection<String> tos, String subject, String content, boolean isHtml, File... files) { |
| | | return send(mailAccount, tos, null, null, subject, content, isHtml, files); |
| | | } |
| | | |
| | | /** |
| | | * åéé®ä»¶ç»å¤äºº |
| | | * |
| | | * @param mailAccount é®ä»¶è´¦æ·ä¿¡æ¯ |
| | | * @param tos æ¶ä»¶äººå表 |
| | | * @param ccs æé人å表ï¼å¯ä»¥ä¸ºnullæç©º |
| | | * @param bccs å¯é人å表ï¼å¯ä»¥ä¸ºnullæç©º |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param isHtml æ¯å¦ä¸ºHTMLæ ¼å¼ |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | * @since 4.0.3 |
| | | */ |
| | | public static String send(MailAccount mailAccount, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, boolean isHtml, File... files) { |
| | | return send(mailAccount, false, tos, ccs, bccs, subject, content, null, isHtml, files); |
| | | } |
| | | |
| | | /** |
| | | * 使ç¨é
ç½®æä»¶ä¸è®¾ç½®çè´¦æ·åéHTMLé®ä»¶ï¼åéç»å个æå¤ä¸ªæ¶ä»¶äºº<br> |
| | | * å¤ä¸ªæ¶ä»¶äººå¯ä»¥ä½¿ç¨éå·â,âåéï¼ä¹å¯ä»¥éè¿åå·â;âåé |
| | | * |
| | | * @param to æ¶ä»¶äºº |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param imageMap å¾çä¸å ä½ç¬¦ï¼å ä½ç¬¦æ ¼å¼ä¸ºcid:$IMAGE_PLACEHOLDER |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | * @since 3.2.0 |
| | | */ |
| | | public static String sendHtml(String to, String subject, String content, Map<String, InputStream> imageMap, File... files) { |
| | | return send(to, subject, content, imageMap, true, files); |
| | | } |
| | | |
| | | /** |
| | | * 使ç¨é
ç½®æä»¶ä¸è®¾ç½®çè´¦æ·åéé®ä»¶ï¼åéå个æå¤ä¸ªæ¶ä»¶äºº<br> |
| | | * å¤ä¸ªæ¶ä»¶äººå¯ä»¥ä½¿ç¨éå·â,âåéï¼ä¹å¯ä»¥éè¿åå·â;âåé |
| | | * |
| | | * @param to æ¶ä»¶äºº |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param imageMap å¾çä¸å ä½ç¬¦ï¼å ä½ç¬¦æ ¼å¼ä¸ºcid:$IMAGE_PLACEHOLDER |
| | | * @param isHtml æ¯å¦ä¸ºHTML |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | */ |
| | | public static String send(String to, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) { |
| | | return send(splitAddress(to), subject, content, imageMap, isHtml, files); |
| | | } |
| | | |
| | | /** |
| | | * 使ç¨é
ç½®æä»¶ä¸è®¾ç½®çè´¦æ·åéé®ä»¶ï¼åéå个æå¤ä¸ªæ¶ä»¶äºº<br> |
| | | * å¤ä¸ªæ¶ä»¶äººãæé人ãå¯é人å¯ä»¥ä½¿ç¨éå·â,âåéï¼ä¹å¯ä»¥éè¿åå·â;âåé |
| | | * |
| | | * @param to æ¶ä»¶äººï¼å¯ä»¥ä½¿ç¨éå·â,âåéï¼ä¹å¯ä»¥éè¿åå·â;âåé |
| | | * @param cc æé人ï¼å¯ä»¥ä½¿ç¨éå·â,âåéï¼ä¹å¯ä»¥éè¿åå·â;âåé |
| | | * @param bcc å¯é人ï¼å¯ä»¥ä½¿ç¨éå·â,âåéï¼ä¹å¯ä»¥éè¿åå·â;âåé |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param imageMap å¾çä¸å ä½ç¬¦ï¼å ä½ç¬¦æ ¼å¼ä¸ºcid:$IMAGE_PLACEHOLDER |
| | | * @param isHtml æ¯å¦ä¸ºHTML |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | * @since 4.0.3 |
| | | */ |
| | | public static String send(String to, String cc, String bcc, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) { |
| | | return send(splitAddress(to), splitAddress(cc), splitAddress(bcc), subject, content, imageMap, isHtml, files); |
| | | } |
| | | |
| | | /** |
| | | * 使ç¨é
ç½®æä»¶ä¸è®¾ç½®çè´¦æ·åéHTMLé®ä»¶ï¼åéç»å¤äºº |
| | | * |
| | | * @param tos æ¶ä»¶äººå表 |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param imageMap å¾çä¸å ä½ç¬¦ï¼å ä½ç¬¦æ ¼å¼ä¸ºcid:$IMAGE_PLACEHOLDER |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | * @since 3.2.0 |
| | | */ |
| | | public static String sendHtml(Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, File... files) { |
| | | return send(tos, subject, content, imageMap, true, files); |
| | | } |
| | | |
| | | /** |
| | | * 使ç¨é
ç½®æä»¶ä¸è®¾ç½®çè´¦æ·åéé®ä»¶ï¼åéç»å¤äºº |
| | | * |
| | | * @param tos æ¶ä»¶äººå表 |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param imageMap å¾çä¸å ä½ç¬¦ï¼å ä½ç¬¦æ ¼å¼ä¸ºcid:$IMAGE_PLACEHOLDER |
| | | * @param isHtml æ¯å¦ä¸ºHTML |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | */ |
| | | public static String send(Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) { |
| | | return send(tos, null, null, subject, content, imageMap, isHtml, files); |
| | | } |
| | | |
| | | /** |
| | | * 使ç¨é
ç½®æä»¶ä¸è®¾ç½®çè´¦æ·åéé®ä»¶ï¼åéç»å¤äºº |
| | | * |
| | | * @param tos æ¶ä»¶äººå表 |
| | | * @param ccs æé人å表ï¼å¯ä»¥ä¸ºnullæç©º |
| | | * @param bccs å¯é人å表ï¼å¯ä»¥ä¸ºnullæç©º |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param imageMap å¾çä¸å ä½ç¬¦ï¼å ä½ç¬¦æ ¼å¼ä¸ºcid:$IMAGE_PLACEHOLDER |
| | | * @param isHtml æ¯å¦ä¸ºHTML |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | * @since 4.0.3 |
| | | */ |
| | | public static String send(Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) { |
| | | return send(getMailAccount(), true, tos, ccs, bccs, subject, content, imageMap, isHtml, files); |
| | | } |
| | | |
| | | // ------------------------------------------------------------------------------------------------------------------------------- Custom MailAccount |
| | | |
| | | /** |
| | | * åéé®ä»¶ç»å¤äºº |
| | | * |
| | | * @param mailAccount é®ä»¶è®¤è¯å¯¹è±¡ |
| | | * @param to æ¶ä»¶äººï¼å¤ä¸ªæ¶ä»¶äººéå·æè
åå·éå¼ |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param imageMap å¾çä¸å ä½ç¬¦ï¼å ä½ç¬¦æ ¼å¼ä¸ºcid:$IMAGE_PLACEHOLDER |
| | | * @param isHtml æ¯å¦ä¸ºHTMLæ ¼å¼ |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | * @since 3.2.0 |
| | | */ |
| | | public static String send(MailAccount mailAccount, String to, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) { |
| | | return send(mailAccount, splitAddress(to), subject, content, imageMap, isHtml, files); |
| | | } |
| | | |
| | | /** |
| | | * åéé®ä»¶ç»å¤äºº |
| | | * |
| | | * @param mailAccount é®ä»¶è´¦æ·ä¿¡æ¯ |
| | | * @param tos æ¶ä»¶äººå表 |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param imageMap å¾çä¸å ä½ç¬¦ï¼å ä½ç¬¦æ ¼å¼ä¸ºcid:$IMAGE_PLACEHOLDER |
| | | * @param isHtml æ¯å¦ä¸ºHTMLæ ¼å¼ |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | * @since 4.6.3 |
| | | */ |
| | | public static String send(MailAccount mailAccount, Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) { |
| | | return send(mailAccount, tos, null, null, subject, content, imageMap, isHtml, files); |
| | | } |
| | | |
| | | /** |
| | | * åéé®ä»¶ç»å¤äºº |
| | | * |
| | | * @param mailAccount é®ä»¶è´¦æ·ä¿¡æ¯ |
| | | * @param tos æ¶ä»¶äººå表 |
| | | * @param ccs æé人å表ï¼å¯ä»¥ä¸ºnullæç©º |
| | | * @param bccs å¯é人å表ï¼å¯ä»¥ä¸ºnullæç©º |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param imageMap å¾çä¸å ä½ç¬¦ï¼å ä½ç¬¦æ ¼å¼ä¸ºcid:$IMAGE_PLACEHOLDER |
| | | * @param isHtml æ¯å¦ä¸ºHTMLæ ¼å¼ |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | * @since 4.6.3 |
| | | */ |
| | | public static String send(MailAccount mailAccount, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, Map<String, InputStream> imageMap, |
| | | boolean isHtml, File... files) { |
| | | return send(mailAccount, false, tos, ccs, bccs, subject, content, imageMap, isHtml, files); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®é
ç½®æä»¶ï¼è·åé®ä»¶å®¢æ·ç«¯ä¼è¯ |
| | | * |
| | | * @param mailAccount é®ä»¶è´¦æ·é
ç½® |
| | | * @param isSingleton æ¯å¦åä¾ï¼å
¨å±å
±äº«ä¼è¯ï¼ |
| | | * @return {@link Session} |
| | | * @since 5.5.7 |
| | | */ |
| | | public static Session getSession(MailAccount mailAccount, boolean isSingleton) { |
| | | Authenticator authenticator = null; |
| | | if (mailAccount.isAuth()) { |
| | | authenticator = new JakartaUserPassAuthenticator(mailAccount.getUser(), mailAccount.getPass()); |
| | | } |
| | | |
| | | return isSingleton ? Session.getDefaultInstance(mailAccount.getSmtpProps(), authenticator) // |
| | | : Session.getInstance(mailAccount.getSmtpProps(), authenticator); |
| | | } |
| | | |
| | | // ------------------------------------------------------------------------------------------------------------------------ Private method start |
| | | |
| | | /** |
| | | * åéé®ä»¶ç»å¤äºº |
| | | * |
| | | * @param mailAccount é®ä»¶è´¦æ·ä¿¡æ¯ |
| | | * @param useGlobalSession æ¯å¦å
¨å±å
񄧮Session |
| | | * @param tos æ¶ä»¶äººå表 |
| | | * @param ccs æé人å表ï¼å¯ä»¥ä¸ºnullæç©º |
| | | * @param bccs å¯é人å表ï¼å¯ä»¥ä¸ºnullæç©º |
| | | * @param subject æ é¢ |
| | | * @param content æ£æ |
| | | * @param imageMap å¾çä¸å ä½ç¬¦ï¼å ä½ç¬¦æ ¼å¼ä¸ºcid:${cid} |
| | | * @param isHtml æ¯å¦ä¸ºHTMLæ ¼å¼ |
| | | * @param files éä»¶å表 |
| | | * @return message-id |
| | | * @since 4.6.3 |
| | | */ |
| | | private static String send(MailAccount mailAccount, boolean useGlobalSession, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, |
| | | Map<String, InputStream> imageMap, boolean isHtml, File... files) { |
| | | final JakartaMail mail = JakartaMail.create(mailAccount).setUseGlobalSession(useGlobalSession); |
| | | |
| | | // å¯éæé人 |
| | | if (CollUtil.isNotEmpty(ccs)) { |
| | | mail.setCcs(ccs.toArray(new String[0])); |
| | | } |
| | | // å¯éå¯é人 |
| | | if (CollUtil.isNotEmpty(bccs)) { |
| | | mail.setBccs(bccs.toArray(new String[0])); |
| | | } |
| | | |
| | | mail.setTos(tos.toArray(new String[0])); |
| | | mail.setTitle(subject); |
| | | mail.setContent(content); |
| | | mail.setHtml(isHtml); |
| | | mail.setFiles(files); |
| | | |
| | | // å¾ç |
| | | if (MapUtil.isNotEmpty(imageMap)) { |
| | | for (Entry<String, InputStream> entry : imageMap.entrySet()) { |
| | | mail.addImage(entry.getKey(), entry.getValue()); |
| | | // å
³éæµ |
| | | IoUtil.close(entry.getValue()); |
| | | } |
| | | } |
| | | |
| | | return mail.send(); |
| | | } |
| | | |
| | | /** |
| | | * å°å¤ä¸ªè系人转为å表ï¼åé符为éå·æè
åå· |
| | | * |
| | | * @param addresses å¤ä¸ªè系人ï¼å¦æä¸ºç©ºè¿ånull |
| | | * @return è系人å表 |
| | | */ |
| | | private static List<String> splitAddress(String addresses) { |
| | | if (StrUtil.isBlank(addresses)) { |
| | | return null; |
| | | } |
| | | |
| | | List<String> result; |
| | | if (StrUtil.contains(addresses, CharUtil.COMMA)) { |
| | | result = StrUtil.splitTrim(addresses, CharUtil.COMMA); |
| | | } else if (StrUtil.contains(addresses, ';')) { |
| | | result = StrUtil.splitTrim(addresses, ';'); |
| | | } else { |
| | | result = CollUtil.newArrayList(addresses); |
| | | } |
| | | return result; |
| | | } |
| | | // ------------------------------------------------------------------------------------------------------------------------ Private method end |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | org.dromara.common.mail.config.MailConfig |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>5.5.3</version> |
| | | </parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-mybatis</artifactId> |
| | | <version>5.5.3</version> |
| | | <description>ruoyi-common-mybatis æ°æ®åºæå¡</description> |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-satoken</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>dynamic-datasource-spring-boot3-starter</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>mybatis-plus-spring-boot3-starter</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>mybatis-plus-jsqlparser</artifactId> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>p6spy</groupId> |
| | | <artifactId>p6spy</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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"> |
| | | <parent> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common</artifactId> |
| | | <version>${revision}</version> |
| | | </parent> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <artifactId>ruoyi-common-mybatis</artifactId> |
| | | |
| | | <description> |
| | | ruoyi-common-mybatis æ°æ®åºæå¡ |
| | | </description> |
| | | |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-core</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.dromara</groupId> |
| | | <artifactId>ruoyi-common-satoken</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- dynamic-datasource 夿°æ®æº--> |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>dynamic-datasource-spring-boot3-starter</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>mybatis-plus-spring-boot3-starter</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.baomidou</groupId> |
| | | <artifactId>mybatis-plus-jsqlparser</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- sqlæ§è½åææä»¶ --> |
| | | <dependency> |
| | | <groupId>p6spy</groupId> |
| | | <artifactId>p6spy</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | </project> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.mybatis.annotation; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * æ°æ®æé注解ï¼ç¨äºæ è®°æ°æ®æéçå ä½ç¬¦å
³é®ååæ¿æ¢å¼ |
| | | * <p> |
| | | * ä¸ä¸ªæ³¨è§£åªè½å¯¹åºä¸ä¸ªæ¨¡æ¿ |
| | | * </p> |
| | | * |
| | | * @author Lion Li |
| | | * @version 3.5.0 |
| | | */ |
| | | @Target(ElementType.METHOD) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @Documented |
| | | public @interface DataColumn { |
| | | |
| | | /** |
| | | * æ°æ®æé模æ¿çå ä½ç¬¦å
³é®åï¼é»è®¤ä¸º "deptName" |
| | | * |
| | | * @return å ä½ç¬¦å
³é®åæ°ç» |
| | | */ |
| | | String[] key() default "deptName"; |
| | | |
| | | /** |
| | | * æ°æ®æé模æ¿çå ä½ç¬¦æ¿æ¢å¼ï¼é»è®¤ä¸º "dept_id" |
| | | * |
| | | * @return å ä½ç¬¦æ¿æ¢å¼æ°ç» |
| | | */ |
| | | String[] value() default "dept_id"; |
| | | |
| | | /** |
| | | * æéæ è¯ç¬¦ ç¨äºéè¿èåæéæ è¯ç¬¦æ¥è·åæ°æ®æé |
| | | * æ¥ææ¤æ è¯ç¬¦çè§è² å°ä¸ä¼æ¼æ¥æ¤è§è²çæ°æ®è¿æ»¤sql |
| | | * |
| | | * @return æéæ è¯ç¬¦ |
| | | */ |
| | | String permission() default ""; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.mybatis.annotation; |
| | | |
| | | import java.lang.annotation.*; |
| | | |
| | | /** |
| | | * æ°æ®æéç»æ³¨è§£ï¼ç¨äºæ è®°æ°æ®æéé
ç½®æ°ç» |
| | | * |
| | | * @author Lion Li |
| | | * @version 3.5.0 |
| | | */ |
| | | @Target({ElementType.METHOD, ElementType.TYPE}) |
| | | @Retention(RetentionPolicy.RUNTIME) |
| | | @Documented |
| | | public @interface DataPermission { |
| | | |
| | | /** |
| | | * æ°æ®æéé
ç½®æ°ç»ï¼ç¨äºæå®æ°æ®æéçå ä½ç¬¦å
³é®ååæ¿æ¢å¼ |
| | | * |
| | | * @return æ°æ®æéé
ç½®æ°ç» |
| | | */ |
| | | DataColumn[] value(); |
| | | |
| | | /** |
| | | * æéæ¼æ¥æ è¯ç¬¦(ç¨äºæå®è¿æ¥è¯å¥çsql符å·) |
| | | * å¦ä¸å¡« é»è®¤ select ç¨ OR å
¶ä»è¯å¥ç¨ AND |
| | | * å
容 OR æè
AND |
| | | */ |
| | | String joinStr() default ""; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.mybatis.aspect; |
| | | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.aopalliance.intercept.MethodInterceptor; |
| | | import org.aopalliance.intercept.MethodInvocation; |
| | | import org.dromara.common.mybatis.annotation.DataPermission; |
| | | import org.dromara.common.mybatis.helper.DataPermissionHelper; |
| | | |
| | | import java.lang.reflect.Method; |
| | | import java.lang.reflect.Proxy; |
| | | |
| | | /** |
| | | * æ°æ®æé注解Advice |
| | | * |
| | | * @author ç§è¾æªå¯ |
| | | */ |
| | | @Slf4j |
| | | public class DataPermissionAdvice implements MethodInterceptor { |
| | | |
| | | @Override |
| | | public Object invoke(MethodInvocation invocation) throws Throwable { |
| | | Object target = invocation.getThis(); |
| | | Method method = invocation.getMethod(); |
| | | Object[] args = invocation.getArguments(); |
| | | // 设置æé注解 |
| | | DataPermissionHelper.setPermission(getDataPermissionAnnotation(target, method, args)); |
| | | try { |
| | | // æ§è¡ä»£çæ¹æ³ |
| | | return invocation.proceed(); |
| | | } finally { |
| | | // æ¸
餿鿳¨è§£ |
| | | DataPermissionHelper.removePermission(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è·åæ°æ®æé注解 |
| | | */ |
| | | private DataPermission getDataPermissionAnnotation(Object target, Method method,Object[] args){ |
| | | DataPermission dataPermission = method.getAnnotation(DataPermission.class); |
| | | // ä¼å
è·åæ¹æ³ä¸ç注解 |
| | | if (dataPermission != null) { |
| | | return dataPermission; |
| | | } |
| | | // æ¹æ³ä¸æ²¡ææ³¨è§£ï¼åè·åç±»ä¸ç注解 |
| | | Class<?> targetClass = target.getClass(); |
| | | // å¦ææ¯ JDK 卿代çï¼åè·åçå®çClasså®ä¾ |
| | | if (Proxy.isProxyClass(targetClass)) { |
| | | targetClass = targetClass.getInterfaces()[0]; |
| | | } |
| | | dataPermission = targetClass.getAnnotation(DataPermission.class); |
| | | return dataPermission; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.mybatis.aspect; |
| | | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.mybatis.annotation.DataPermission; |
| | | import org.springframework.aop.support.StaticMethodMatcherPointcut; |
| | | |
| | | import java.lang.reflect.Method; |
| | | import java.lang.reflect.Proxy; |
| | | |
| | | /** |
| | | * æ°æ®æéå¹é
åç¹ |
| | | * |
| | | * @author ç§è¾æªå¯ |
| | | */ |
| | | @Slf4j |
| | | @SuppressWarnings("all") |
| | | public class DataPermissionPointcut extends StaticMethodMatcherPointcut { |
| | | |
| | | @Override |
| | | public boolean matches(Method method, Class<?> targetClass) { |
| | | // ä¼å
å¹é
æ¹æ³ |
| | | // æ°æ®æé注解ä¸å¯¹ç»§æ¿çæï¼æä»¥æ£æ¥å½åæ¹æ³æ¯å¦ææ³¨è§£å³å¯ï¼ä¸åå¾ä¸å¹é
ç¶ç±»ææ¥å£ |
| | | if (method.isAnnotationPresent(DataPermission.class)) { |
| | | return true; |
| | | } |
| | | |
| | | // MyBatis ç Mapper å°±æ¯éè¿ JDK 卿代çå®ç°çï¼æä»¥è¿ééè¦æ£æ¥æ¯å¦å¹é
JDK ç卿代ç |
| | | Class<?> targetClassRef = targetClass; |
| | | if (Proxy.isProxyClass(targetClassRef)) { |
| | | // æ°æ®æé注解ä¸å¯¹ç»§æ¿çæï¼ä½ç±äº SpringIOC 容卿¿å°çå®é
䏿¯ MyBatis 代çè¿åç Mapperï¼è targetClass.isAnnotationPresent å®é
å¹é
çæ¯ Proxy ç±»çæ³¨è§£ï¼ä¸ä¼æ¥æ¾ä»£çç±»ã |
| | | // æä»¥è¿éä¸è½ç¨ targetClass.isAnnotationPresentï¼åªè½ç¨ AnnotatedElementUtils.hasAnnotation æ targetClass.getInterfaces()[0].isAnnotationPresent å»åå¹é
ï¼ä»¥æ£æ¥è¢«ä»£çç MapperClass æ¯å¦å
·ææ³¨è§£ |
| | | // åçï¼JDK å¨æä»£çæ¬è´¨ä¸å°±æ¯å¯¹æ¥å£è¿è¡å®ç°ç¶å对å
·ä½çæ¥å£å®ç°å代çï¼æä»¥ç´æ¥éè¿æ¥å£å¯ä»¥æ¿å°å®é
ç MapperClass |
| | | targetClassRef = targetClass.getInterfaces()[0]; |
| | | |
| | | } |
| | | return targetClassRef.isAnnotationPresent(DataPermission.class); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.mybatis.aspect; |
| | | |
| | | import org.aopalliance.aop.Advice; |
| | | import org.springframework.aop.Pointcut; |
| | | import org.springframework.aop.support.AbstractPointcutAdvisor; |
| | | |
| | | /** |
| | | * æ°æ®æé注解åé¢å®ä¹ |
| | | * |
| | | * @author ç§è¾æªå¯ |
| | | */ |
| | | @SuppressWarnings("all") |
| | | public class DataPermissionPointcutAdvisor extends AbstractPointcutAdvisor { |
| | | |
| | | private final Advice advice; |
| | | private final Pointcut pointcut; |
| | | |
| | | public DataPermissionPointcutAdvisor() { |
| | | this.advice = new DataPermissionAdvice(); |
| | | this.pointcut = new DataPermissionPointcut(); |
| | | } |
| | | |
| | | @Override |
| | | public Pointcut getPointcut() { |
| | | return this.pointcut; |
| | | } |
| | | |
| | | @Override |
| | | public Advice getAdvice() { |
| | | return this.advice; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.mybatis.config; |
| | | |
| | | import cn.hutool.core.net.NetUtil; |
| | | import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; |
| | | import com.baomidou.mybatisplus.core.handlers.PostInitTableInfoHandler; |
| | | import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator; |
| | | import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator; |
| | | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; |
| | | import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; |
| | | import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; |
| | | import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; |
| | | import org.dromara.common.core.factory.YmlPropertySourceFactory; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.dromara.common.mybatis.aspect.DataPermissionPointcutAdvisor; |
| | | import org.dromara.common.mybatis.handler.InjectionMetaObjectHandler; |
| | | import org.dromara.common.mybatis.handler.MybatisExceptionHandler; |
| | | import org.dromara.common.mybatis.handler.PlusPostInitTableInfoHandler; |
| | | import org.dromara.common.mybatis.interceptor.PlusDataPermissionInterceptor; |
| | | import org.mybatis.spring.annotation.MapperScan; |
| | | import org.springframework.beans.BeansException; |
| | | import org.springframework.beans.factory.config.BeanDefinition; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.PropertySource; |
| | | import org.springframework.context.annotation.Role; |
| | | import org.springframework.transaction.annotation.EnableTransactionManagement; |
| | | |
| | | /** |
| | | * mybatis-plusé
置类(䏿¹æ³¨éææä»¶ä»ç») |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Role(BeanDefinition.ROLE_INFRASTRUCTURE) |
| | | @EnableTransactionManagement(proxyTargetClass = true) |
| | | @MapperScan("${mybatis-plus.mapperPackage}") |
| | | @PropertySource(value = "classpath:common-mybatis.yml", factory = YmlPropertySourceFactory.class) |
| | | public class MybatisPlusConfig { |
| | | |
| | | @Bean |
| | | public MybatisPlusInterceptor mybatisPlusInterceptor() { |
| | | MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); |
| | | // å¤ç§æ·æä»¶ å¿
é¡»æ¾å°ç¬¬ä¸ä½ |
| | | try { |
| | | TenantLineInnerInterceptor tenant = SpringUtils.getBean(TenantLineInnerInterceptor.class); |
| | | interceptor.addInnerInterceptor(tenant); |
| | | } catch (BeansException ignore) { |
| | | } |
| | | // æ°æ®æéå¤ç |
| | | interceptor.addInnerInterceptor(dataPermissionInterceptor()); |
| | | // å页æä»¶ |
| | | interceptor.addInnerInterceptor(paginationInnerInterceptor()); |
| | | // ä¹è§éæä»¶ |
| | | interceptor.addInnerInterceptor(optimisticLockerInnerInterceptor()); |
| | | return interceptor; |
| | | } |
| | | |
| | | /** |
| | | * æ°æ®æéæ¦æªå¨ |
| | | */ |
| | | public PlusDataPermissionInterceptor dataPermissionInterceptor() { |
| | | return new PlusDataPermissionInterceptor(); |
| | | } |
| | | |
| | | /** |
| | | * æ°æ®æéåé¢å¤çå¨ |
| | | */ |
| | | @Bean |
| | | @Role(BeanDefinition.ROLE_INFRASTRUCTURE) |
| | | public DataPermissionPointcutAdvisor dataPermissionPointcutAdvisor() { |
| | | return new DataPermissionPointcutAdvisor(); |
| | | } |
| | | |
| | | /** |
| | | * å页æä»¶ï¼èªå¨è¯å«æ°æ®åºç±»å |
| | | */ |
| | | public PaginationInnerInterceptor paginationInnerInterceptor() { |
| | | PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(); |
| | | // å页åçå |
| | | paginationInnerInterceptor.setOverflow(true); |
| | | return paginationInnerInterceptor; |
| | | } |
| | | |
| | | /** |
| | | * ä¹è§éæä»¶ |
| | | */ |
| | | public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor() { |
| | | return new OptimisticLockerInnerInterceptor(); |
| | | } |
| | | |
| | | /** |
| | | * å
å¯¹è±¡åæ®µå¡«å
æ§å¶å¨ |
| | | */ |
| | | @Bean |
| | | public MetaObjectHandler metaObjectHandler() { |
| | | return new InjectionMetaObjectHandler(); |
| | | } |
| | | |
| | | /** |
| | | * 使ç¨ç½å¡ä¿¡æ¯ç»å®éªè±çæå¨ |
| | | * 鲿¢é群éªè±IDéå¤ |
| | | */ |
| | | @Bean |
| | | public IdentifierGenerator idGenerator() { |
| | | return new DefaultIdentifierGenerator(NetUtil.getLocalhost()); |
| | | } |
| | | |
| | | /** |
| | | * å¼å¸¸å¤çå¨ |
| | | */ |
| | | @Bean |
| | | public MybatisExceptionHandler mybatisExceptionHandler() { |
| | | return new MybatisExceptionHandler(); |
| | | } |
| | | |
| | | /** |
| | | * åå§å表对象å¤çå¨ |
| | | */ |
| | | @Bean |
| | | public PostInitTableInfoHandler postInitTableInfoHandler() { |
| | | return new PlusPostInitTableInfoHandler(); |
| | | } |
| | | |
| | | /** |
| | | * PaginationInnerInterceptor å页æä»¶ï¼èªå¨è¯å«æ°æ®åºç±»å |
| | | * https://baomidou.com/pages/97710a/ |
| | | * OptimisticLockerInnerInterceptor ä¹è§éæä»¶ |
| | | * https://baomidou.com/pages/0d93c0/ |
| | | * MetaObjectHandler å
å¯¹è±¡åæ®µå¡«å
æ§å¶å¨ |
| | | * https://baomidou.com/pages/4c6bcf/ |
| | | * ISqlInjector sql注å
¥å¨ |
| | | * https://baomidou.com/pages/42ea4a/ |
| | | * BlockAttackInnerInterceptor 妿æ¯å¯¹å
¨è¡¨çå é¤ææ´æ°æä½ï¼å°±ä¼ç»æ¢è¯¥æä½ |
| | | * https://baomidou.com/pages/f9a237/ |
| | | * IllegalSQLInnerInterceptor sqlæ§è½è§èæä»¶(åå¾SQLæ¦æª) |
| | | * IdentifierGenerator èªå®ä¹ä¸»é®çç¥ |
| | | * https://baomidou.com/pages/568eb2/ |
| | | * TenantLineInnerInterceptor å¤ç§æ·æä»¶ |
| | | * https://baomidou.com/pages/aef2f2/ |
| | | * DynamicTableNameInnerInterceptor å¨æè¡¨åæä»¶ |
| | | * https://baomidou.com/pages/2a45ff/ |
| | | */ |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.mybatis.core.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.FieldFill; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.fasterxml.jackson.annotation.JsonIgnore; |
| | | import com.fasterxml.jackson.annotation.JsonInclude; |
| | | import lombok.Data; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * Entityåºç±» |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Data |
| | | public class BaseEntity implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * æç´¢å¼ |
| | | */ |
| | | @JsonIgnore |
| | | @TableField(exist = false) |
| | | private String searchValue; |
| | | |
| | | /** |
| | | * å建é¨é¨ |
| | | */ |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private Long createDept; |
| | | |
| | | /** |
| | | * å建è
|
| | | */ |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private Long createBy; |
| | | |
| | | /** |
| | | * å建æ¶é´ |
| | | */ |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private Date createTime; |
| | | |
| | | /** |
| | | * æ´æ°è
|
| | | */ |
| | | @TableField(fill = FieldFill.INSERT_UPDATE) |
| | | private Long updateBy; |
| | | |
| | | /** |
| | | * æ´æ°æ¶é´ |
| | | */ |
| | | @TableField(fill = FieldFill.INSERT_UPDATE) |
| | | private Date updateTime; |
| | | |
| | | /** |
| | | * 请æ±åæ° |
| | | */ |
| | | @JsonInclude(JsonInclude.Include.NON_EMPTY) |
| | | @TableField(exist = false) |
| | | private Map<String, Object> params = new HashMap<>(); |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.mybatis.core.mapper; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.Wrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.reflect.GenericTypeUtils; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.toolkit.Db; |
| | | import org.apache.ibatis.logging.Log; |
| | | import org.apache.ibatis.logging.LogFactory; |
| | | import org.dromara.common.core.utils.MapstructUtils; |
| | | import org.dromara.common.core.utils.StreamUtils; |
| | | |
| | | import java.io.Serializable; |
| | | import java.util.Collection; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.function.Function; |
| | | |
| | | /** |
| | | * èªå®ä¹ Mapper æ¥å£, å®ç° èªå®ä¹æ©å± |
| | | * |
| | | * @param <T> table æ³å |
| | | * @param <V> vo æ³å |
| | | * @author Lion Li |
| | | * @since 2021-05-13 |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public interface BaseMapperPlus<T, V> extends BaseMapper<T> { |
| | | |
| | | Log log = LogFactory.getLog(BaseMapperPlus.class); |
| | | |
| | | /** |
| | | * è·åå½åå®ä¾å¯¹è±¡å
³èçæ³åç±»å V ç Class 对象 |
| | | * |
| | | * @return è¿åå½åå®ä¾å¯¹è±¡å
³èçæ³åç±»å V ç Class 对象 |
| | | */ |
| | | default Class<V> currentVoClass() { |
| | | return (Class<V>) GenericTypeUtils.resolveTypeArguments(this.getClass(), BaseMapperPlus.class)[1]; |
| | | } |
| | | |
| | | /** |
| | | * è·åå½åå®ä¾å¯¹è±¡å
³èçæ³åç±»å T ç Class 对象 |
| | | * |
| | | * @return è¿åå½åå®ä¾å¯¹è±¡å
³èçæ³åç±»å T ç Class 对象 |
| | | */ |
| | | default Class<T> currentModelClass() { |
| | | return (Class<T>) GenericTypeUtils.resolveTypeArguments(this.getClass(), BaseMapperPlus.class)[0]; |
| | | } |
| | | |
| | | /** |
| | | * 使ç¨é»è®¤çæ¥è¯¢æ¡ä»¶æ¥è¯¢å¹¶è¿åç»æå表 |
| | | * |
| | | * @return è¿åæ¥è¯¢ç»æçå表 |
| | | */ |
| | | default List<T> selectList() { |
| | | return this.selectList(new QueryWrapper<>()); |
| | | } |
| | | |
| | | /** |
| | | * æ¹éæå
¥å®ä½å¯¹è±¡éå |
| | | * |
| | | * @param entityList å®ä½å¯¹è±¡éå |
| | | * @return æå
¥æä½æ¯å¦æåçå¸å°å¼ |
| | | */ |
| | | default boolean insertBatch(Collection<T> entityList) { |
| | | return Db.saveBatch(entityList); |
| | | } |
| | | |
| | | /** |
| | | * æ¹éæ ¹æ®IDæ´æ°å®ä½å¯¹è±¡éå |
| | | * |
| | | * @param entityList å®ä½å¯¹è±¡éå |
| | | * @return æ´æ°æä½æ¯å¦æåçå¸å°å¼ |
| | | */ |
| | | default boolean updateBatchById(Collection<T> entityList) { |
| | | return Db.updateBatchById(entityList); |
| | | } |
| | | |
| | | /** |
| | | * æ¹éæå
¥ææ´æ°å®ä½å¯¹è±¡éå |
| | | * |
| | | * @param entityList å®ä½å¯¹è±¡éå |
| | | * @return æå
¥ææ´æ°æä½æ¯å¦æåçå¸å°å¼ |
| | | */ |
| | | default boolean insertOrUpdateBatch(Collection<T> entityList) { |
| | | return Db.saveOrUpdateBatch(entityList); |
| | | } |
| | | |
| | | /** |
| | | * æ¹éæå
¥å®ä½å¯¹è±¡éåå¹¶æå®æ¹å¤çå¤§å° |
| | | * |
| | | * @param entityList å®ä½å¯¹è±¡éå |
| | | * @param batchSize æ¹å¤çå¤§å° |
| | | * @return æå
¥æä½æ¯å¦æåçå¸å°å¼ |
| | | */ |
| | | default boolean insertBatch(Collection<T> entityList, int batchSize) { |
| | | return Db.saveBatch(entityList, batchSize); |
| | | } |
| | | |
| | | /** |
| | | * æ¹éæ ¹æ®IDæ´æ°å®ä½å¯¹è±¡éåå¹¶æå®æ¹å¤çå¤§å° |
| | | * |
| | | * @param entityList å®ä½å¯¹è±¡éå |
| | | * @param batchSize æ¹å¤çå¤§å° |
| | | * @return æ´æ°æä½æ¯å¦æåçå¸å°å¼ |
| | | */ |
| | | default boolean updateBatchById(Collection<T> entityList, int batchSize) { |
| | | return Db.updateBatchById(entityList, batchSize); |
| | | } |
| | | |
| | | /** |
| | | * æ¹éæå
¥ææ´æ°å®ä½å¯¹è±¡éåå¹¶æå®æ¹å¤çå¤§å° |
| | | * |
| | | * @param entityList å®ä½å¯¹è±¡éå |
| | | * @param batchSize æ¹å¤çå¤§å° |
| | | * @return æå
¥ææ´æ°æä½æ¯å¦æåçå¸å°å¼ |
| | | */ |
| | | default boolean insertOrUpdateBatch(Collection<T> entityList, int batchSize) { |
| | | return Db.saveOrUpdateBatch(entityList, batchSize); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®IDæ¥è¯¢å个VO对象 |
| | | * |
| | | * @param id 主é®ID |
| | | * @return æ¥è¯¢å°çå个VO对象 |
| | | */ |
| | | default V selectVoById(Serializable id) { |
| | | return selectVoById(id, this.currentVoClass()); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®IDæ¥è¯¢å个VO对象并å°å
¶è½¬æ¢ä¸ºæå®çVOç±» |
| | | * |
| | | * @param id 主é®ID |
| | | * @param voClass è¦è½¬æ¢çVOç±»çClass对象 |
| | | * @param <C> VOç±»çç±»å |
| | | * @return æ¥è¯¢å°çå个VO对象ï¼ç»è¿è½¬æ¢ä¸ºæå®çVOç±»åè¿å |
| | | */ |
| | | default <C> C selectVoById(Serializable id, Class<C> voClass) { |
| | | T obj = this.selectById(id); |
| | | if (ObjectUtil.isNull(obj)) { |
| | | return null; |
| | | } |
| | | return MapstructUtils.convert(obj, voClass); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®IDéåæ¹éæ¥è¯¢VO对象å表 |
| | | * |
| | | * @param idList 主é®IDéå |
| | | * @return æ¥è¯¢å°çVO对象å表 |
| | | */ |
| | | default List<V> selectVoByIds(Collection<? extends Serializable> idList) { |
| | | return selectVoByIds(idList, this.currentVoClass()); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®IDéåæ¹éæ¥è¯¢å®ä½å¯¹è±¡å表ï¼å¹¶å°å
¶è½¬æ¢ä¸ºæå®çVO对象å表 |
| | | * |
| | | * @param idList 主é®IDéå |
| | | * @param voClass è¦è½¬æ¢çVOç±»çClass对象 |
| | | * @param <C> VOç±»çç±»å |
| | | * @return æ¥è¯¢å°çVO对象å表ï¼ç»è¿è½¬æ¢ä¸ºæå®çVOç±»åè¿å |
| | | */ |
| | | default <C> List<C> selectVoByIds(Collection<? extends Serializable> idList, Class<C> voClass) { |
| | | List<T> list = this.selectByIds(idList); |
| | | if (CollUtil.isEmpty(list)) { |
| | | return CollUtil.newArrayList(); |
| | | } |
| | | return MapstructUtils.convert(list, voClass); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®æ¥è¯¢æ¡ä»¶Mapæ¥è¯¢VO对象å表 |
| | | * |
| | | * @param map æ¥è¯¢æ¡ä»¶Map |
| | | * @return æ¥è¯¢å°çVO对象å表 |
| | | */ |
| | | default List<V> selectVoByMap(Map<String, Object> map) { |
| | | return selectVoByMap(map, this.currentVoClass()); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®æ¥è¯¢æ¡ä»¶Mapæ¥è¯¢å®ä½å¯¹è±¡å表ï¼å¹¶å°å
¶è½¬æ¢ä¸ºæå®çVO对象å表 |
| | | * |
| | | * @param map æ¥è¯¢æ¡ä»¶Map |
| | | * @param voClass è¦è½¬æ¢çVOç±»çClass对象 |
| | | * @param <C> VOç±»çç±»å |
| | | * @return æ¥è¯¢å°çVO对象å表ï¼ç»è¿è½¬æ¢ä¸ºæå®çVOç±»åè¿å |
| | | */ |
| | | default <C> List<C> selectVoByMap(Map<String, Object> map, Class<C> voClass) { |
| | | List<T> list = this.selectByMap(map); |
| | | if (CollUtil.isEmpty(list)) { |
| | | return CollUtil.newArrayList(); |
| | | } |
| | | return MapstructUtils.convert(list, voClass); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®æ¡ä»¶æ¥è¯¢å个VO对象 |
| | | * |
| | | * @param wrapper æ¥è¯¢æ¡ä»¶Wrapper |
| | | * @return æ¥è¯¢å°çå个VO对象 |
| | | */ |
| | | default V selectVoOne(Wrapper<T> wrapper) { |
| | | return selectVoOne(wrapper, this.currentVoClass()); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®æ¡ä»¶æ¥è¯¢å个VO对象ï¼å¹¶æ ¹æ®éè¦å³å®æ¯å¦æåºå¼å¸¸ |
| | | * |
| | | * @param wrapper æ¥è¯¢æ¡ä»¶Wrapper |
| | | * @param throwEx æ¯å¦æåºå¼å¸¸çæ å¿ |
| | | * @return æ¥è¯¢å°çå个VO对象 |
| | | */ |
| | | default V selectVoOne(Wrapper<T> wrapper, boolean throwEx) { |
| | | return selectVoOne(wrapper, this.currentVoClass(), throwEx); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®æ¡ä»¶æ¥è¯¢å个VO对象ï¼å¹¶æå®è¿åçVO对象çç±»å |
| | | * |
| | | * @param wrapper æ¥è¯¢æ¡ä»¶Wrapper |
| | | * @param voClass è¿åçVO对象çClass对象 |
| | | * @param <C> è¿åçVO对象çç±»å |
| | | * @return æ¥è¯¢å°çå个VO对象ï¼ç»è¿ç±»å转æ¢ä¸ºæå®çVOç±»åè¿å |
| | | */ |
| | | default <C> C selectVoOne(Wrapper<T> wrapper, Class<C> voClass) { |
| | | return selectVoOne(wrapper, voClass, true); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®æ¡ä»¶æ¥è¯¢å个å®ä½å¯¹è±¡ï¼å¹¶å°å
¶è½¬æ¢ä¸ºæå®çVO对象 |
| | | * |
| | | * @param wrapper æ¥è¯¢æ¡ä»¶Wrapper |
| | | * @param voClass è¦è½¬æ¢çVOç±»çClass对象 |
| | | * @param throwEx æ¯å¦æåºå¼å¸¸çæ å¿ |
| | | * @param <C> VOç±»çç±»å |
| | | * @return æ¥è¯¢å°çå个VO对象ï¼ç»è¿è½¬æ¢ä¸ºæå®çVOç±»åè¿å |
| | | */ |
| | | default <C> C selectVoOne(Wrapper<T> wrapper, Class<C> voClass, boolean throwEx) { |
| | | T obj = this.selectOne(wrapper, throwEx); |
| | | if (ObjectUtil.isNull(obj)) { |
| | | return null; |
| | | } |
| | | return MapstructUtils.convert(obj, voClass); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢ææVO对象å表 |
| | | * |
| | | * @return æ¥è¯¢å°çVO对象å表 |
| | | */ |
| | | default List<V> selectVoList() { |
| | | return selectVoList(new QueryWrapper<>(), this.currentVoClass()); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®æ¡ä»¶æ¥è¯¢VO对象å表 |
| | | * |
| | | * @param wrapper æ¥è¯¢æ¡ä»¶Wrapper |
| | | * @return æ¥è¯¢å°çVO对象å表 |
| | | */ |
| | | default List<V> selectVoList(Wrapper<T> wrapper) { |
| | | return selectVoList(wrapper, this.currentVoClass()); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®æ¡ä»¶æ¥è¯¢å®ä½å¯¹è±¡å表ï¼å¹¶å°å
¶è½¬æ¢ä¸ºæå®çVO对象å表 |
| | | * |
| | | * @param wrapper æ¥è¯¢æ¡ä»¶Wrapper |
| | | * @param voClass è¦è½¬æ¢çVOç±»çClass对象 |
| | | * @param <C> VOç±»çç±»å |
| | | * @return æ¥è¯¢å°çVO对象å表ï¼ç»è¿è½¬æ¢ä¸ºæå®çVOç±»åè¿å |
| | | */ |
| | | default <C> List<C> selectVoList(Wrapper<T> wrapper, Class<C> voClass) { |
| | | List<T> list = this.selectList(wrapper); |
| | | if (CollUtil.isEmpty(list)) { |
| | | return CollUtil.newArrayList(); |
| | | } |
| | | return MapstructUtils.convert(list, voClass); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®æ¡ä»¶å页æ¥è¯¢VO对象å表 |
| | | * |
| | | * @param page åé¡µä¿¡æ¯ |
| | | * @param wrapper æ¥è¯¢æ¡ä»¶Wrapper |
| | | * @return æ¥è¯¢å°çVO对象å页å表 |
| | | */ |
| | | default <P extends IPage<V>> P selectVoPage(IPage<T> page, Wrapper<T> wrapper) { |
| | | return selectVoPage(page, wrapper, this.currentVoClass()); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®æ¡ä»¶å页æ¥è¯¢å®ä½å¯¹è±¡å表ï¼å¹¶å°å
¶è½¬æ¢ä¸ºæå®çVO对象å页å表 |
| | | * |
| | | * @param page åé¡µä¿¡æ¯ |
| | | * @param wrapper æ¥è¯¢æ¡ä»¶Wrapper |
| | | * @param voClass è¦è½¬æ¢çVOç±»çClass对象 |
| | | * @param <C> VOç±»çç±»å |
| | | * @param <P> VO对象å页å表çç±»å |
| | | * @return æ¥è¯¢å°çVO对象å页å表ï¼ç»è¿è½¬æ¢ä¸ºæå®çVOç±»åè¿å |
| | | */ |
| | | default <C, P extends IPage<C>> P selectVoPage(IPage<T> page, Wrapper<T> wrapper, Class<C> voClass) { |
| | | // æ ¹æ®æ¡ä»¶å页æ¥è¯¢å®ä½å¯¹è±¡å表 |
| | | List<T> list = this.selectList(page, wrapper); |
| | | // å建ä¸ä¸ªæ°çVO对象å页å表ï¼å¹¶è®¾ç½®åé¡µä¿¡æ¯ |
| | | IPage<C> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal()); |
| | | if (CollUtil.isEmpty(list)) { |
| | | return (P) voPage; |
| | | } |
| | | voPage.setRecords(MapstructUtils.convert(list, voClass)); |
| | | return (P) voPage; |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®æ¡ä»¶æ¥è¯¢ç¬¦åæ¡ä»¶ç对象ï¼å¹¶å°å
¶è½¬æ¢ä¸ºæå®ç±»åç对象å表 |
| | | * |
| | | * @param wrapper æ¥è¯¢æ¡ä»¶Wrapper |
| | | * @param mapper 转æ¢å½æ°ï¼ç¨äºå°æ¥è¯¢å°ç对象转æ¢ä¸ºæå®ç±»åç对象 |
| | | * @param <C> è¦è½¬æ¢ç对象çç±»å |
| | | * @return æ¥è¯¢å°çç¬¦åæ¡ä»¶ç对象å表ï¼ç»è¿è½¬æ¢ä¸ºæå®ç±»åç对象åè¿å |
| | | */ |
| | | default <C> List<C> selectObjs(Wrapper<T> wrapper, Function<? super Object, C> mapper) { |
| | | return StreamUtils.toList(this.selectObjs(wrapper), mapper); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.mybatis.core.page; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.baomidou.mybatisplus.core.metadata.OrderItem; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.fasterxml.jackson.annotation.JsonIgnore; |
| | | import lombok.Data; |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.core.utils.sql.SqlUtil; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * å页æ¥è¯¢å®ä½ç±» |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Data |
| | | public class PageQuery implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * åé¡µå¤§å° |
| | | */ |
| | | private Integer pageSize; |
| | | |
| | | /** |
| | | * å½åé¡µæ° |
| | | */ |
| | | private Integer pageNum; |
| | | |
| | | /** |
| | | * æåºå |
| | | */ |
| | | private String orderByColumn; |
| | | |
| | | /** |
| | | * æåºçæ¹ådescæè
asc |
| | | */ |
| | | private String isAsc; |
| | | |
| | | /** |
| | | * å½åè®°å½èµ·å§ç´¢å¼ é»è®¤å¼ |
| | | */ |
| | | public static final int DEFAULT_PAGE_NUM = 1; |
| | | |
| | | /** |
| | | * æ¯é¡µæ¾ç¤ºè®°å½æ° é»è®¤å¼ é»è®¤æ¥å
¨é¨ |
| | | */ |
| | | public static final int DEFAULT_PAGE_SIZE = Integer.MAX_VALUE; |
| | | |
| | | /** |
| | | * æå»ºå页对象 |
| | | */ |
| | | public <T> Page<T> build() { |
| | | Integer pageNum = ObjectUtil.defaultIfNull(getPageNum(), DEFAULT_PAGE_NUM); |
| | | Integer pageSize = ObjectUtil.defaultIfNull(getPageSize(), DEFAULT_PAGE_SIZE); |
| | | if (pageNum <= 0) { |
| | | pageNum = DEFAULT_PAGE_NUM; |
| | | } |
| | | Page<T> page = new Page<>(pageNum, pageSize); |
| | | List<OrderItem> orderItems = buildOrderItem(); |
| | | if (CollUtil.isNotEmpty(orderItems)) { |
| | | page.addOrder(orderItems); |
| | | } |
| | | return page; |
| | | } |
| | | |
| | | /** |
| | | * æå»ºæåº |
| | | * |
| | | * æ¯æçç¨æ³å¦ä¸: |
| | | * {isAsc:"asc",orderByColumn:"id"} order by id asc |
| | | * {isAsc:"asc",orderByColumn:"id,createTime"} order by id asc,create_time asc |
| | | * {isAsc:"desc",orderByColumn:"id,createTime"} order by id desc,create_time desc |
| | | * {isAsc:"asc,desc",orderByColumn:"id,createTime"} order by id asc,create_time desc |
| | | */ |
| | | private List<OrderItem> buildOrderItem() { |
| | | if (StringUtils.isBlank(orderByColumn) || StringUtils.isBlank(isAsc)) { |
| | | return null; |
| | | } |
| | | String orderBy = SqlUtil.escapeOrderBySql(orderByColumn); |
| | | orderBy = StringUtils.toUnderScoreCase(orderBy); |
| | | |
| | | // å
¼å®¹å端æåºç±»å |
| | | isAsc = StringUtils.replaceEach(isAsc, new String[]{"ascending", "descending"}, new String[]{"asc", "desc"}); |
| | | |
| | | String[] orderByArr = orderBy.split(StringUtils.SEPARATOR); |
| | | String[] isAscArr = isAsc.split(StringUtils.SEPARATOR); |
| | | if (isAscArr.length != 1 && isAscArr.length != orderByArr.length) { |
| | | throw new ServiceException("æåºåæ°æè¯¯"); |
| | | } |
| | | |
| | | List<OrderItem> list = new ArrayList<>(); |
| | | // æ¯ä¸ªå段åèªæåº |
| | | for (int i = 0; i < orderByArr.length; i++) { |
| | | String orderByStr = orderByArr[i]; |
| | | String isAscStr = isAscArr.length == 1 ? isAscArr[0] : isAscArr[i]; |
| | | if ("asc".equals(isAscStr)) { |
| | | list.add(OrderItem.asc(orderByStr)); |
| | | } else if ("desc".equals(isAscStr)) { |
| | | list.add(OrderItem.desc(orderByStr)); |
| | | } else { |
| | | throw new ServiceException("æåºåæ°æè¯¯"); |
| | | } |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | @JsonIgnore |
| | | public Integer getFirstNum() { |
| | | return (pageNum - 1) * pageSize; |
| | | } |
| | | |
| | | public PageQuery(Integer pageSize, Integer pageNum) { |
| | | this.pageSize = pageSize; |
| | | this.pageNum = pageNum; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.mybatis.core.page; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.http.HttpStatus; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import lombok.Data; |
| | | import lombok.NoArgsConstructor; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * è¡¨æ ¼åé¡µæ°æ®å¯¹è±¡ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Data |
| | | @NoArgsConstructor |
| | | public class TableDataInfo<T> implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | /** |
| | | * æ»è®°å½æ° |
| | | */ |
| | | private long total; |
| | | |
| | | /** |
| | | * åè¡¨æ°æ® |
| | | */ |
| | | private List<T> rows; |
| | | |
| | | /** |
| | | * æ¶æ¯ç¶æç |
| | | */ |
| | | private int code; |
| | | |
| | | /** |
| | | * æ¶æ¯å
容 |
| | | */ |
| | | private String msg; |
| | | |
| | | /** |
| | | * å页 |
| | | * |
| | | * @param list åè¡¨æ°æ® |
| | | * @param total æ»è®°å½æ° |
| | | */ |
| | | public TableDataInfo(List<T> list, long total) { |
| | | this.rows = list; |
| | | this.total = total; |
| | | this.code = HttpStatus.HTTP_OK; |
| | | this.msg = "æ¥è¯¢æå"; |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®å页对象æå»ºè¡¨æ ¼åé¡µæ°æ®å¯¹è±¡ |
| | | */ |
| | | public static <T> TableDataInfo<T> build(IPage<T> page) { |
| | | TableDataInfo<T> rspData = new TableDataInfo<>(); |
| | | rspData.setCode(HttpStatus.HTTP_OK); |
| | | rspData.setMsg("æ¥è¯¢æå"); |
| | | rspData.setRows(page.getRecords()); |
| | | rspData.setTotal(page.getTotal()); |
| | | return rspData; |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®æ°æ®å表æå»ºè¡¨æ ¼åé¡µæ°æ®å¯¹è±¡ |
| | | */ |
| | | public static <T> TableDataInfo<T> build(List<T> list) { |
| | | TableDataInfo<T> rspData = new TableDataInfo<>(); |
| | | rspData.setCode(HttpStatus.HTTP_OK); |
| | | rspData.setMsg("æ¥è¯¢æå"); |
| | | rspData.setRows(list); |
| | | rspData.setTotal(list.size()); |
| | | return rspData; |
| | | } |
| | | |
| | | /** |
| | | * æå»ºè¡¨æ ¼åé¡µæ°æ®å¯¹è±¡ |
| | | */ |
| | | public static <T> TableDataInfo<T> build() { |
| | | TableDataInfo<T> rspData = new TableDataInfo<>(); |
| | | rspData.setCode(HttpStatus.HTTP_OK); |
| | | rspData.setMsg("æ¥è¯¢æå"); |
| | | return rspData; |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®åå§æ°æ®å表ååé¡µåæ°ï¼æå»ºè¡¨æ ¼åé¡µæ°æ®å¯¹è±¡ï¼ç¨äºååé¡µï¼ |
| | | * |
| | | * @param list åå§æ°æ®å表ï¼å
¨é¨æ°æ®ï¼ |
| | | * @param page åé¡µåæ°å¯¹è±¡ï¼å
å«å½å页ç ãæ¯é¡µå¤§å°çï¼ |
| | | * @return æé 好çåé¡µç»æ TableDataInfo<T> |
| | | */ |
| | | public static <T> TableDataInfo<T> build(List<T> list, IPage<T> page) { |
| | | if (CollUtil.isEmpty(list)) { |
| | | return TableDataInfo.build(); |
| | | } |
| | | List<T> pageList = CollUtil.page((int) page.getCurrent() - 1, (int) page.getSize(), list); |
| | | return new TableDataInfo<>(pageList, list.size()); |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.mybatis.enums; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | |
| | | /** |
| | | * æ°æ®åºç±»å |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum DataBaseType { |
| | | |
| | | /** |
| | | * MySQL |
| | | */ |
| | | MY_SQL("MySQL"), |
| | | |
| | | /** |
| | | * Oracle |
| | | */ |
| | | ORACLE("Oracle"), |
| | | |
| | | /** |
| | | * PostgreSQL |
| | | */ |
| | | POSTGRE_SQL("PostgreSQL"), |
| | | |
| | | /** |
| | | * SQL Server |
| | | */ |
| | | SQL_SERVER("Microsoft SQL Server"); |
| | | |
| | | /** |
| | | * æ°æ®åºç±»å |
| | | */ |
| | | private final String type; |
| | | |
| | | /** |
| | | * æ ¹æ®æ°æ®åºäº§ååç§°æ¥æ¾å¯¹åºçæ°æ®åºç±»å |
| | | * |
| | | * @param databaseProductName æ°æ®åºäº§ååç§° |
| | | * @return 对åºçæ°æ®åºç±»åæä¸¾å¼ |
| | | */ |
| | | public static DataBaseType find(String databaseProductName) { |
| | | if (StringUtils.isBlank(databaseProductName)) { |
| | | return MY_SQL; |
| | | } |
| | | for (DataBaseType type : values()) { |
| | | if (type.getType().equals(databaseProductName)) { |
| | | return type; |
| | | } |
| | | } |
| | | return MY_SQL; |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦ä¸º MySQL ç±»å |
| | | */ |
| | | public boolean isMySql() { |
| | | return this == MY_SQL; |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦ä¸º Oracle ç±»å |
| | | */ |
| | | public boolean isOracle() { |
| | | return this == ORACLE; |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦ä¸º PostgreSQL ç±»å |
| | | */ |
| | | public boolean isPostgreSql() { |
| | | return this == POSTGRE_SQL; |
| | | } |
| | | |
| | | /** |
| | | * 夿æ¯å¦ä¸º SQL Server ç±»å |
| | | */ |
| | | public boolean isSqlServer() { |
| | | return this == SQL_SERVER; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.mybatis.enums; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Getter; |
| | | import org.dromara.common.core.domain.model.LoginUser; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.mybatis.helper.DataPermissionHelper; |
| | | |
| | | /** |
| | | * æ°æ®æéç±»åæä¸¾ |
| | | * <p> |
| | | * æ¯æä½¿ç¨ SpEL 模æ¿è¡¨è¾¾å¼å®ä¹ SQL æ¥è¯¢æ¡ä»¶ |
| | | * å
ç½®æ°æ®ï¼ |
| | | * - {@code user}: å½åç»å½ç¨æ·ä¿¡æ¯ï¼åè {@link LoginUser} |
| | | * å
ç½®æå¡ï¼ |
| | | * - {@code sdss}: ç³»ç»æ°æ®æéæå¡ï¼åè ISysDataScopeService |
| | | * å¦éæ©å±æ°æ®ï¼å¯ä»¥éè¿ {@link DataPermissionHelper} è¿è¡æä½ |
| | | * å¦éæ©å±æå¡ï¼å¯ä»¥éè¿ ISysDataScopeService èªè¡ç¼å |
| | | * </p> |
| | | * |
| | | * @author Lion Li |
| | | * @version 3.5.0 |
| | | */ |
| | | @Getter |
| | | @AllArgsConstructor |
| | | public enum DataScopeType { |
| | | |
| | | /** |
| | | * å
¨é¨æ°æ®æé |
| | | */ |
| | | ALL("1", "", ""), |
| | | |
| | | /** |
| | | * èªå®æ°æ®æé |
| | | */ |
| | | CUSTOM("2", " #{#deptName} IN ( #{@sdss.getRoleCustom( #user.roleId )} ) ", " 1 = 0 "), |
| | | |
| | | /** |
| | | * é¨é¨æ°æ®æé |
| | | */ |
| | | DEPT("3", " #{#deptName} = #{#user.deptId} ", " 1 = 0 "), |
| | | |
| | | /** |
| | | * é¨é¨å以䏿°æ®æé |
| | | */ |
| | | DEPT_AND_CHILD("4", " #{#deptName} IN ( #{@sdss.getDeptAndChild( #user.deptId )} )", " 1 = 0 "), |
| | | |
| | | /** |
| | | * ä»
æ¬äººæ°æ®æé |
| | | */ |
| | | SELF("5", " #{#userName} = #{#user.userId} ", " 1 = 0 "), |
| | | |
| | | /** |
| | | * é¨é¨å以䏿æ¬äººæ°æ®æé |
| | | */ |
| | | DEPT_AND_CHILD_OR_SELF("6", " #{#deptName} IN ( #{@sdss.getDeptAndChild( #user.deptId )} ) OR #{#userName} = #{#user.userId} ", " 1 = 0 "); |
| | | |
| | | private final String code; |
| | | |
| | | /** |
| | | * SpEL 模æ¿è¡¨è¾¾å¼ï¼ç¨äºæå»º SQL æ¥è¯¢æ¡ä»¶ |
| | | */ |
| | | private final String sqlTemplate; |
| | | |
| | | /** |
| | | * 妿䏿»¡è¶³ {@code sqlTemplate} çæ¡ä»¶ï¼åä½¿ç¨æ¤é»è®¤ SQL è¡¨è¾¾å¼ |
| | | */ |
| | | private final String elseSql; |
| | | |
| | | /** |
| | | * æ ¹æ®æä¸¾ä»£ç æ¥æ¾å¯¹åºçæä¸¾å¼ |
| | | * |
| | | * @param code æä¸¾ä»£ç |
| | | * @return 对åºçæä¸¾å¼ï¼å¦ææªæ¾å°åè¿å null |
| | | */ |
| | | public static DataScopeType findCode(String code) { |
| | | if (StringUtils.isBlank(code)) { |
| | | return null; |
| | | } |
| | | for (DataScopeType type : values()) { |
| | | if (type.getCode().equals(code)) { |
| | | return type; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.mybatis.handler; |
| | | |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import cn.hutool.http.HttpStatus; |
| | | import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.ibatis.reflection.MetaObject; |
| | | import org.dromara.common.core.domain.model.LoginUser; |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | import org.dromara.common.core.utils.ObjectUtils; |
| | | import org.dromara.common.mybatis.core.domain.BaseEntity; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * MP注å
¥å¤çå¨ |
| | | * |
| | | * @author Lion Li |
| | | * @date 2021/4/25 |
| | | */ |
| | | @Slf4j |
| | | public class InjectionMetaObjectHandler implements MetaObjectHandler { |
| | | |
| | | /** |
| | | * å¦æç¨æ·ä¸åå¨é»è®¤æ³¨å
¥-1代表æ ç¨æ· |
| | | */ |
| | | private static final Long DEFAULT_USER_ID = -1L; |
| | | |
| | | /** |
| | | * æå
¥å¡«å
æ¹æ³ï¼ç¨äºå¨æå
¥æ°æ®æ¶èªå¨å¡«å
å®ä½å¯¹è±¡ä¸çå建æ¶é´ãæ´æ°æ¶é´ãåå»ºäººãæ´æ°äººçä¿¡æ¯ |
| | | * |
| | | * @param metaObject å
对象ï¼ç¨äºè·ååå§å¯¹è±¡å¹¶è¿è¡å¡«å
|
| | | */ |
| | | @Override |
| | | public void insertFill(MetaObject metaObject) { |
| | | try { |
| | | if (ObjectUtil.isNotNull(metaObject) && metaObject.getOriginalObject() instanceof BaseEntity baseEntity) { |
| | | // è·åå½åæ¶é´ä½ä¸ºå建æ¶é´åæ´æ°æ¶é´ï¼å¦æå建æ¶é´ä¸ä¸ºç©ºï¼å使ç¨å建æ¶é´ï¼å¦å使ç¨å½åæ¶é´ |
| | | Date current = ObjectUtils.notNull(baseEntity.getCreateTime(), new Date()); |
| | | baseEntity.setCreateTime(current); |
| | | baseEntity.setUpdateTime(current); |
| | | |
| | | // 妿å建人为空ï¼åå¡«å
å½åç»å½ç¨æ·çä¿¡æ¯ |
| | | if (ObjectUtil.isNull(baseEntity.getCreateBy())) { |
| | | LoginUser loginUser = getLoginUser(); |
| | | if (ObjectUtil.isNotNull(loginUser)) { |
| | | Long userId = loginUser.getUserId(); |
| | | // å¡«å
åå»ºäººãæ´æ°äººåå建é¨é¨ä¿¡æ¯ |
| | | baseEntity.setCreateBy(userId); |
| | | baseEntity.setUpdateBy(userId); |
| | | baseEntity.setCreateDept(ObjectUtils.notNull(baseEntity.getCreateDept(), loginUser.getDeptId())); |
| | | } else { |
| | | // å¡«å
åå»ºäººãæ´æ°äººåå建é¨é¨ä¿¡æ¯ |
| | | baseEntity.setCreateBy(DEFAULT_USER_ID); |
| | | baseEntity.setUpdateBy(DEFAULT_USER_ID); |
| | | baseEntity.setCreateDept(ObjectUtils.notNull(baseEntity.getCreateDept(), DEFAULT_USER_ID)); |
| | | } |
| | | } |
| | | } else { |
| | | Date date = new Date(); |
| | | this.strictInsertFill(metaObject, "createTime", Date.class, date); |
| | | this.strictInsertFill(metaObject, "updateTime", Date.class, date); |
| | | } |
| | | } catch (Exception e) { |
| | | throw new ServiceException("èªå¨æ³¨å
¥å¼å¸¸ => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ´æ°å¡«å
æ¹æ³ï¼ç¨äºå¨æ´æ°æ°æ®æ¶èªå¨å¡«å
å®ä½å¯¹è±¡ä¸çæ´æ°æ¶é´åæ´æ°äººä¿¡æ¯ |
| | | * |
| | | * @param metaObject å
对象ï¼ç¨äºè·ååå§å¯¹è±¡å¹¶è¿è¡å¡«å
|
| | | */ |
| | | @Override |
| | | public void updateFill(MetaObject metaObject) { |
| | | try { |
| | | if (ObjectUtil.isNotNull(metaObject) && metaObject.getOriginalObject() instanceof BaseEntity baseEntity) { |
| | | // è·åå½åæ¶é´ä½ä¸ºæ´æ°æ¶é´ï¼æ 论åå§å¯¹è±¡ä¸çæ´æ°æ¶é´æ¯å¦ä¸ºç©ºé½å¡«å
|
| | | Date current = new Date(); |
| | | baseEntity.setUpdateTime(current); |
| | | |
| | | // è·åå½åç»å½ç¨æ·çIDï¼å¹¶å¡«å
æ´æ°äººä¿¡æ¯ |
| | | Long userId = LoginHelper.getUserId(); |
| | | if (ObjectUtil.isNotNull(userId)) { |
| | | baseEntity.setUpdateBy(userId); |
| | | } else { |
| | | baseEntity.setUpdateBy(DEFAULT_USER_ID); |
| | | } |
| | | } else { |
| | | this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date()); |
| | | } |
| | | } catch (Exception e) { |
| | | throw new ServiceException("èªå¨æ³¨å
¥å¼å¸¸ => " + e.getMessage(), HttpStatus.HTTP_UNAUTHORIZED); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * è·åå½åç»å½ç¨æ·ä¿¡æ¯ |
| | | * |
| | | * @return å½åç»å½ç¨æ·çä¿¡æ¯ï¼å¦æç¨æ·æªç»å½åè¿å null |
| | | */ |
| | | private LoginUser getLoginUser() { |
| | | LoginUser loginUser; |
| | | try { |
| | | loginUser = LoginHelper.getLoginUser(); |
| | | } catch (Exception e) { |
| | | return null; |
| | | } |
| | | return loginUser; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.mybatis.handler; |
| | | |
| | | import cn.dev33.satoken.exception.NotLoginException; |
| | | import cn.hutool.http.HttpStatus; |
| | | import com.baomidou.dynamic.datasource.exception.CannotFindDataSourceException; |
| | | import jakarta.servlet.http.HttpServletRequest; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.core.domain.R; |
| | | import org.mybatis.spring.MyBatisSystemException; |
| | | import org.springframework.dao.DuplicateKeyException; |
| | | import org.springframework.web.bind.annotation.ExceptionHandler; |
| | | import org.springframework.web.bind.annotation.RestControllerAdvice; |
| | | |
| | | /** |
| | | * Mybatiså¼å¸¸å¤çå¨ |
| | | * |
| | | * @author Lion Li |
| | | */ |
| | | @Slf4j |
| | | @RestControllerAdvice |
| | | public class MybatisExceptionHandler { |
| | | |
| | | /** |
| | | * 䏻鮿UNIQUEç´¢å¼ï¼æ°æ®éå¤å¼å¸¸ |
| | | */ |
| | | @ExceptionHandler(DuplicateKeyException.class) |
| | | public R<Void> handleDuplicateKeyException(DuplicateKeyException e, HttpServletRequest request) { |
| | | String requestURI = request.getRequestURI(); |
| | | log.error("请æ±å°å'{}',æ°æ®åºä¸å·²åå¨è®°å½'{}'", requestURI, e.getMessage()); |
| | | return R.fail(HttpStatus.HTTP_CONFLICT, "æ°æ®åºä¸å·²åå¨è¯¥è®°å½ï¼è¯·è系管çå确认"); |
| | | } |
| | | |
| | | /** |
| | | * Mybatisç³»ç»å¼å¸¸ éç¨å¤ç |
| | | */ |
| | | @ExceptionHandler(MyBatisSystemException.class) |
| | | public R<Void> handleCannotFindDataSourceException(MyBatisSystemException e, HttpServletRequest request) { |
| | | String requestURI = request.getRequestURI(); |
| | | Throwable root = getRootCause(e); |
| | | if (root instanceof NotLoginException) { |
| | | log.error("请æ±å°å'{}',认è¯å¤±è´¥'{}',æ æ³è®¿é®ç³»ç»èµæº", requestURI, root.getMessage()); |
| | | return R.fail(HttpStatus.HTTP_UNAUTHORIZED, "认è¯å¤±è´¥ï¼æ æ³è®¿é®ç³»ç»èµæº"); |
| | | } |
| | | if (root instanceof CannotFindDataSourceException) { |
| | | log.error("请æ±å°å'{}', æªæ¾å°æ°æ®æº", requestURI); |
| | | return R.fail(HttpStatus.HTTP_INTERNAL_ERROR, "æªæ¾å°æ°æ®æºï¼è¯·è系管çå确认"); |
| | | } |
| | | log.error("请æ±å°å'{}', Mybatisç³»ç»å¼å¸¸", requestURI, e); |
| | | return R.fail(HttpStatus.HTTP_INTERNAL_ERROR, e.getMessage()); |
| | | } |
| | | |
| | | /** |
| | | * è·åå¼å¸¸çæ ¹å ï¼é彿¥æ¾ï¼ |
| | | * |
| | | * @param e å½åå¼å¸¸ |
| | | * @return æ ¹å å¼å¸¸ï¼æåºå±ç causeï¼ |
| | | * <p> |
| | | * é»è¾è¯´æï¼ |
| | | * 1. 妿 e 没æ causeï¼è¯´æ e æ¬èº«å°±æ¯æ ¹å ï¼ç´æ¥è¿å |
| | | * 2. 妿 e ç cause åèªèº«ç¸åï¼é²æ¢å¾ªç¯å¼ç¨ï¼ï¼ä¹è¿å e |
| | | * 3. å¦åéå½è°ç¨ï¼ç»§ç»åä¸å¯»æ¾æåºå±ç cause |
| | | */ |
| | | public static Throwable getRootCause(Throwable e) { |
| | | Throwable cause = e.getCause(); |
| | | if (cause == null || cause == e) { |
| | | return e; |
| | | } |
| | | return getRootCause(cause); |
| | | } |
| | | |
| | | /** |
| | | * å¨å¼å¸¸é¾ä¸æ¥æ¾æå®ç±»åçå¼å¸¸ |
| | | * |
| | | * @param e å½åå¼å¸¸ |
| | | * @param clazz ç®æ å¼å¸¸ç±» |
| | | * @return æ¾å°çæå®ç±»åå¼å¸¸ï¼å¦ææ²¡ææ¾å°è¿å null |
| | | */ |
| | | public static Throwable findCause(Throwable e, Class<? extends Throwable> clazz) { |
| | | Throwable t = e; |
| | | while (t != null && t != t.getCause()) { |
| | | if (clazz.isInstance(t)) { |
| | | return t; |
| | | } |
| | | t = t.getCause(); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.common.mybatis.handler; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import net.sf.jsqlparser.JSQLParserException; |
| | | import net.sf.jsqlparser.expression.Expression; |
| | | import net.sf.jsqlparser.expression.operators.conditional.AndExpression; |
| | | import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; |
| | | import net.sf.jsqlparser.parser.CCJSqlParserUtil; |
| | | import org.dromara.common.core.domain.dto.RoleDTO; |
| | | import org.dromara.common.core.domain.model.LoginUser; |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | import org.dromara.common.core.utils.SpringUtils; |
| | | import org.dromara.common.core.utils.StreamUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.mybatis.annotation.DataColumn; |
| | | import org.dromara.common.mybatis.annotation.DataPermission; |
| | | import org.dromara.common.mybatis.enums.DataScopeType; |
| | | import org.dromara.common.mybatis.helper.DataPermissionHelper; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | import org.springframework.context.expression.BeanFactoryResolver; |
| | | import org.springframework.expression.*; |
| | | import org.springframework.expression.common.TemplateParserContext; |
| | | import org.springframework.expression.spel.standard.SpelExpressionParser; |
| | | import org.springframework.expression.spel.support.StandardEvaluationContext; |
| | | |
| | | import java.util.*; |
| | | import java.util.function.Function; |
| | | |
| | | /** |
| | | * æ°æ®æéè¿æ»¤ |
| | | * |
| | | * @author Lion Li |
| | | * @version 3.5.0 |
| | | */ |
| | | @Slf4j |
| | | public class PlusDataPermissionHandler { |
| | | |
| | | /** |
| | | * spel è§£æå¨ |
| | | */ |
| | | private final ExpressionParser parser = new SpelExpressionParser(); |
| | | private final ParserContext parserContext = new TemplateParserContext(); |
| | | /** |
| | | * beanè§£æå¨ ç¨äºå¤ç spel 表达å¼ä¸å¯¹ bean çè°ç¨ |
| | | */ |
| | | private final BeanResolver beanResolver = new BeanFactoryResolver(SpringUtils.getBeanFactory()); |
| | | |
| | | /** |
| | | * è·åæ°æ®è¿æ»¤æ¡ä»¶ç SQL çæ®µ |
| | | * |
| | | * @param where åå§çæ¥è¯¢æ¡ä»¶è¡¨è¾¾å¼ |
| | | * @param isSelect æ¯å¦ä¸ºæ¥è¯¢è¯å¥ |
| | | * @return æ°æ®è¿æ»¤æ¡ä»¶ç SQL çæ®µ |
| | | */ |
| | | public Expression getSqlSegment(Expression where, boolean isSelect) { |
| | | try { |
| | | // è·åæ°æ®æéé
ç½® |
| | | DataPermission dataPermission = getDataPermission(); |
| | | // è·åå½åç»å½ç¨æ·ä¿¡æ¯ |
| | | LoginUser currentUser = DataPermissionHelper.getVariable("user"); |
| | | if (ObjectUtil.isNull(currentUser)) { |
| | | currentUser = LoginHelper.getLoginUser(); |
| | | DataPermissionHelper.setVariable("user", currentUser); |
| | | } |
| | | // 妿æ¯è¶
级管çåæç§æ·ç®¡çåï¼åä¸è¿æ»¤æ°æ® |
| | | if (LoginHelper.isSuperAdmin() || LoginHelper.isTenantAdmin()) { |
| | | return where; |
| | | } |
| | | // æé æ°æ®è¿æ»¤æ¡ä»¶ç SQL çæ®µ |
| | | String dataFilterSql = buildDataFilter(dataPermission, isSelect); |
| | | if (StringUtils.isBlank(dataFilterSql)) { |
| | | return where; |
| | | } |
| | | Expression expression = CCJSqlParserUtil.parseExpression(dataFilterSql); |
| | | // æ°æ®æé使ç¨åç¬çæ¬å· 鲿¢ä¸å
¶ä»æ¡ä»¶å²çª |
| | | ParenthesedExpressionList<Expression> parenthesis = new ParenthesedExpressionList<>(expression); |
| | | if (ObjectUtil.isNotNull(where)) { |
| | | return new AndExpression(where, parenthesis); |
| | | } else { |
| | | return parenthesis; |
| | | } |
| | | } catch (JSQLParserException e) { |
| | | throw new ServiceException("æ°æ®æéè§£æå¼å¸¸ => " + e.getMessage()); |
| | | } finally { |
| | | DataPermissionHelper.removePermission(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æå»ºæ°æ®è¿æ»¤æ¡ä»¶ç SQL è¯å¥ |
| | | * |
| | | * @param dataPermission æ°æ®æé注解 |
| | | * @param isSelect æ å¿å½åæä½æ¯å¦ä¸ºæ¥è¯¢æä½ï¼æ¥è¯¢æä½åæ´æ°æå 餿ä½å¨å¤çè¿æ»¤æ¡ä»¶æ¶ä¼æä¸åçå¤çæ¹å¼ |
| | | * @return æå»ºçæ°æ®è¿æ»¤æ¡ä»¶ç SQL è¯å¥ |
| | | * @throws ServiceException 妿è§è²çæ°æ®èå´å¼å¸¸æè
key ä¸ value çé¿åº¦ä¸å¹é
ï¼åæåº ServiceException å¼å¸¸ |
| | | */ |
| | | private String buildDataFilter(DataPermission dataPermission, boolean isSelect) { |
| | | // æ´æ°æå é¤éæ»¡è¶³æææ¡ä»¶ |
| | | String joinStr = isSelect ? " OR " : " AND "; |
| | | if (StringUtils.isNotBlank(dataPermission.joinStr())) { |
| | | joinStr = " " + dataPermission.joinStr() + " "; |
| | | } |
| | | LoginUser user = DataPermissionHelper.getVariable("user"); |
| | | Object defaultValue = "-1"; |
| | | NullSafeStandardEvaluationContext context = new NullSafeStandardEvaluationContext(defaultValue); |
| | | context.addPropertyAccessor(new NullSafePropertyAccessor(context.getPropertyAccessors().get(0), defaultValue)); |
| | | context.setBeanResolver(beanResolver); |
| | | DataPermissionHelper.getContext().forEach(context::setVariable); |
| | | Set<String> conditions = new HashSet<>(); |
| | | // ä¼å
设置åé |
| | | List<String> keys = new ArrayList<>(); |
| | | Map<DataColumn, Boolean> ignoreMap = new HashMap<>(); |
| | | for (DataColumn dataColumn : dataPermission.value()) { |
| | | if (dataColumn.key().length != dataColumn.value().length) { |
| | | throw new ServiceException("è§è²æ°æ®èå´å¼å¸¸ => keyä¸valueé¿åº¦ä¸å¹é
"); |
| | | } |
| | | // å
å«æéæ è¯ç¬¦ è¿ç´æ¥è·³è¿ |
| | | if (StringUtils.isNotBlank(dataColumn.permission()) && |
| | | CollUtil.contains(user.getMenuPermission(), dataColumn.permission()) |
| | | ) { |
| | | ignoreMap.put(dataColumn, Boolean.TRUE); |
| | | continue; |
| | | } |
| | | // 设置注解åé key 为表达å¼åé value 为åéå¼ |
| | | for (int i = 0; i < dataColumn.key().length; i++) { |
| | | context.setVariable(dataColumn.key()[i], dataColumn.value()[i]); |
| | | } |
| | | keys.addAll(Arrays.stream(dataColumn.key()).map(key -> "#" + key).toList()); |
| | | } |
| | | |
| | | for (RoleDTO role : user.getRoles()) { |
| | | user.setRoleId(role.getRoleId()); |
| | | // è·åè§è²æéæ³å |
| | | DataScopeType type = DataScopeType.findCode(role.getDataScope()); |
| | | if (ObjectUtil.isNull(type)) { |
| | | throw new ServiceException("è§è²æ°æ®èå´å¼å¸¸ => " + role.getDataScope()); |
| | | } |
| | | // å
¨é¨æ°æ®æéç´æ¥è¿å |
| | | if (type == DataScopeType.ALL) { |
| | | return StringUtils.EMPTY; |
| | | } |
| | | boolean isSuccess = false; |
| | | for (DataColumn dataColumn : dataPermission.value()) { |
| | | // å
å«æéæ è¯ç¬¦ è¿ç´æ¥è·³è¿ |
| | | if (ignoreMap.containsKey(dataColumn)) { |
| | | // ä¿®å¤å¤è§è²ä¸æéæ è¯ç¬¦å
±ç¨é®é¢ https://gitee.com/dromara/RuoYi-Vue-Plus/issues/IB4CS4 |
| | | conditions.add(joinStr + " 1 = 1 "); |
| | | isSuccess = true; |
| | | continue; |
| | | } |
| | | // ä¸å
å« key åé åä¸å¤ç |
| | | if (!StringUtils.containsAny(type.getSqlTemplate(), keys.toArray(String[]::new))) { |
| | | continue; |
| | | } |
| | | // å½åæ³¨è§£ä¸æ»¡è¶³æ¨¡æ¿ ä¸å¤ç |
| | | if (!StringUtils.containsAny(type.getSqlTemplate(), dataColumn.key())) { |
| | | continue; |
| | | } |
| | | // å¿½ç¥æ°æ®æé 鲿¢spel表达å¼å
æå
¶ä»sqlæ¥è¯¢å¯¼è´æ»å¾ªç¯è°ç¨ |
| | | String sql = DataPermissionHelper.ignore(() -> |
| | | parser.parseExpression(type.getSqlTemplate(), parserContext).getValue(context, String.class) |
| | | ); |
| | | // è§£æsql模æ¿å¹¶å¡«å
|
| | | conditions.add(joinStr + sql); |
| | | isSuccess = true; |
| | | } |
| | | // æªå¤çæååå¡«å
å
åºæ¹æ¡ |
| | | if (!isSuccess && StringUtils.isNotBlank(type.getElseSql())) { |
| | | conditions.add(joinStr + type.getElseSql()); |
| | | } |
| | | } |
| | | |
| | | if (CollUtil.isNotEmpty(conditions)) { |
| | | String sql = StreamUtils.join(conditions, Function.identity(), ""); |
| | | return sql.substring(joinStr.length()); |
| | | } |
| | | return StringUtils.EMPTY; |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®æ å°è¯å¥ ID æç±»åè·å对åºç DataPermission 注解对象 |
| | | * |
| | | * @return DataPermission 注解对象ï¼å¦æä¸åå¨åè¿å null |
| | | */ |
| | | public DataPermission getDataPermission() { |
| | | return DataPermissionHelper.getPermission(); |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥ç»å®çæ å°è¯å¥ ID æ¯å¦ææï¼å³æ¯å¦è½å¤æ¾å°å¯¹åºç DataPermission 注解对象 |
| | | * |
| | | * @return 妿æ¾å°å¯¹åºç DataPermission 注解对象ï¼åè¿å falseï¼å¦åè¿å true |
| | | */ |
| | | public boolean invalid() { |
| | | return getDataPermission() == null; |
| | | } |
| | | |
| | | /** |
| | | * 对æænullåéæ¾ä¸å°çåéè¿åé»è®¤å¼ |
| | | */ |
| | | @AllArgsConstructor |
| | | private static class NullSafeStandardEvaluationContext extends StandardEvaluationContext { |
| | | |
| | | private final Object defaultValue; |
| | | |
| | | @Override |
| | | public Object lookupVariable(String name) { |
| | | Object obj = super.lookupVariable(name); |
| | | // å¦æè¯»åå°ç弿¯ nullï¼åè¿åé»è®¤å¼ |
| | | if (obj == null) { |
| | | return defaultValue; |
| | | } |
| | | return obj; |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 对æænullåéæ¾ä¸å°çåéè¿åé»è®¤å¼ å§ææ¨¡å¼ å°ä¸éè¦å¤ççæ¹æ³å§æç»åå¤çå¨ |
| | | */ |
| | | @AllArgsConstructor |
| | | private static class NullSafePropertyAccessor implements PropertyAccessor { |
| | | |
| | | private final PropertyAccessor delegate; |
| | | private final Object defaultValue; |
| | | |
| | | @Override |
| | | public Class<?>[] getSpecificTargetClasses() { |
| | | return delegate.getSpecificTargetClasses(); |
| | | } |
| | | |
| | | @Override |
| | | public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException { |
| | | return delegate.canRead(context, target, name); |
| | | } |
| | | |
| | | @Override |
| | | public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException { |
| | | TypedValue value = delegate.read(context, target, name); |
| | | // å¦æè¯»åå°ç弿¯ nullï¼åè¿åé»è®¤å¼ |
| | | if (value.getValue() == null) { |
| | | return new TypedValue(defaultValue); |
| | | } |
| | | return value; |
| | | } |
| | | |
| | | @Override |
| | | public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException { |
| | | return delegate.canWrite(context, target, name); |
| | | } |
| | | |
| | | @Override |
| | | public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException { |
| | | delegate.write(context, target, name, newValue); |
| | | } |
| | | } |
| | | |
| | | } |
| RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/handler/PlusPostInitTableInfoHandler.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/helper/DataBaseHelper.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/helper/DataPermissionHelper.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/interceptor/PlusDataPermissionInterceptor.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-mybatis/src/main/java/org/dromara/common/mybatis/utils/IdGeneratorUtil.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-mybatis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-mybatis/src/main/resources/common-mybatis.yml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-mybatis/src/main/resources/spy.properties
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-oss/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-oss/pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/constant/OssConstant.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/OssClient.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/core/WriteOutSubscriber.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/entity/UploadResult.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/enums/AccessPolicyType.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/exception/OssException.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/factory/OssFactory.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-oss/src/main/java/org/dromara/common/oss/properties/OssProperties.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-ratelimiter/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-ratelimiter/pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/annotation/RateLimiter.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/aspectj/RateLimiterAspect.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/config/RateLimiterConfig.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-ratelimiter/src/main/java/org/dromara/common/ratelimiter/enums/LimitType.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-ratelimiter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-ratelimiter/src/main/resources/spel-extension.json
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-redis/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-redis/pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/CacheConfig.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/RedisConfig.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/config/properties/RedissonProperties.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/handler/KeyPrefixHandler.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/handler/RedisExceptionHandler.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/CaffeineCacheDecorator.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/manager/PlusSpringCacheManager.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/CacheUtils.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/QueueUtils.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/RedisUtils.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-redis/src/main/java/org/dromara/common/redis/utils/SequenceUtils.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-satoken/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-satoken/pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/config/SaTokenConfig.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/dao/PlusSaTokenDao.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/core/service/SaPermissionImpl.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/handler/SaTokenExceptionHandler.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-satoken/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-satoken/src/main/resources/common-satoken.yml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-security/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-security/pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/SecurityConfig.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/properties/SecurityProperties.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/handler/AllUrlHandler.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-security/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sensitive/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sensitive/pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/annotation/Sensitive.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/core/SensitiveService.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/core/SensitiveStrategy.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sensitive/src/main/java/org/dromara/common/sensitive/handler/SensitiveHandler.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sms/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sms/pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/config/SmsAutoConfiguration.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/core/dao/PlusSmsDao.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sms/src/main/java/org/dromara/common/sms/handler/SmsExceptionHandler.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sms/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-social/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-social/pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AbstractAuthWeChatEnterpriseRequest.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-social/src/main/java/me/zhyd/oauth/request/AuthDingTalkV2Request.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/SocialAutoConfiguration.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialLoginConfigProperties.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/config/properties/SocialProperties.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/gitea/AuthGiteaRequest.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/gitea/AuthGiteaSource.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeyRequest.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/maxkey/AuthMaxKeySource.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamRequest.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/topiam/AuthTopIamSource.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/AuthRedisStateCache.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-social/src/main/java/org/dromara/common/social/utils/SocialUtils.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-social/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sse/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sse/pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/config/SseAutoConfiguration.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/config/SseProperties.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/controller/SseController.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/core/SseEmitterManager.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/dto/SseMessageDto.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/listener/SseTopicListener.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sse/src/main/java/org/dromara/common/sse/utils/SseMessageUtils.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-sse/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-tenant/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-tenant/pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/config/TenantConfig.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/core/TenantEntity.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/core/TenantSaTokenDao.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/exception/TenantException.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/PlusTenantLineHandler.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/handle/TenantKeyPrefixHandler.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/manager/TenantSpringCacheManager.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/properties/TenantProperties.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-tenant/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/annotation/Translation.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/annotation/TranslationType.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/config/TranslationConfig.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/constant/TransConstant.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/TranslationInterface.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/handler/TranslationBeanSerializerModifier.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/handler/TranslationHandler.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/impl/DeptNameTranslationImpl.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/impl/DictTypeTranslationImpl.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/impl/NicknameTranslationImpl.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/impl/OssUrlTranslationImpl.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/java/org/dromara/common/translation/core/impl/UserNameTranslationImpl.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-translation/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-web/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-web/pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/CaptchaConfig.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/FilterConfig.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/I18nConfig.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/ResourcesConfig.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/UndertowConfig.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/properties/CaptchaProperties.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/config/properties/XssProperties.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/core/BaseController.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/core/I18nLocaleResolver.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/core/WaveAndCircleCaptcha.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/filter/RepeatableFilter.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/filter/RepeatedlyRequestWrapper.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/filter/XssFilter.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/filter/XssHttpServletRequestWrapper.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/handler/GlobalExceptionHandler.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-web/src/main/java/org/dromara/common/web/interceptor/PlusWebInvokeTimeInterceptor.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-websocket/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-websocket/pom.xml
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/config/WebSocketConfig.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/config/properties/WebSocketProperties.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/constant/WebSocketConstants.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/dto/WebSocketMessageDto.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/handler/PlusWebSocketHandler.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/holder/WebSocketSessionHolder.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/interceptor/PlusWebSocketInterceptor.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/listener/WebSocketTopicListener.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-websocket/src/main/java/org/dromara/common/websocket/utils/WebSocketUtils.java
RuoYi-Vue-Plus/ruoyi-common/ruoyi-common-websocket/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
RuoYi-Vue-Plus/ruoyi-extend/.DS_Store
RuoYi-Vue-Plus/ruoyi-extend/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-extend/pom.xml
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-monitor-admin/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-monitor-admin/Dockerfile
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-monitor-admin/pom.xml
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-monitor-admin/src/main/java/org/dromara/monitor/admin/MonitorAdminApplication.java
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-monitor-admin/src/main/java/org/dromara/monitor/admin/config/SecurityConfig.java
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-monitor-admin/src/main/java/org/dromara/monitor/admin/notifier/CustomNotifier.java
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/banner.txt
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/logback-plus.xml
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-snailjob-server/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-snailjob-server/Dockerfile
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-snailjob-server/pom.xml
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/filter/ActuatorAuthFilter.java
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-snailjob-server/src/main/java/com/aizuda/snailjob/server/starter/filter/SecurityConfig.java
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-snailjob-server/src/main/java/org/dromara/snailjob/SnailJobServerApplication.java
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-dev.yml
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application-prod.yml
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/application.yml
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/banner.txt
RuoYi-Vue-Plus/ruoyi-extend/ruoyi-snailjob-server/src/main/resources/logback-plus.xml
RuoYi-Vue-Plus/ruoyi-modules/.DS_Store
RuoYi-Vue-Plus/ruoyi-modules/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-modules/pom.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/pom.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/MailSendController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisCacheController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisLockController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisPubSubController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/RedisRateLimiterController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/SmsController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/Swagger3DemoController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestBatchController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestDemoController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestEncryptController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestExcelController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestI18nController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestSensitiveController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/TestTreeController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/WebSocketController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/package-info.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/queue/BoundedQueueController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/queue/DelayedQueueController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/queue/PriorityDemo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/controller/queue/PriorityQueueController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/TestDemo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/TestDemoEncrypt.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/TestTree.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/bo/TestDemoBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/bo/TestDemoImportVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/bo/TestTreeBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/package-info.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/ExportDemoVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/TestDemoVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/domain/vo/TestTreeVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/listener/ExportDemoListener.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/TestDemoEncryptMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/TestDemoMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/TestTreeMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/mapper/package-info.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/IExportExcelService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/ITestDemoService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/ITestTreeService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/ExportExcelServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/TestDemoServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/TestTreeServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/impl/package-info.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/java/org/dromara/demo/service/package-info.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/resources/excel/单列表.xlsx
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/resources/excel/多sheet列表.xlsx
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/resources/excel/多列表.xlsx
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/resources/mapper/demo/TestDemoMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/resources/mapper/demo/TestTreeMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-demo/src/main/resources/mapper/package-info.md
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/pom.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/config/GenConfig.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/config/MyBatisDataSourceMonitor.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/constant/GenConstants.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/controller/GenController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/domain/GenTable.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/domain/GenTableColumn.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/mapper/GenTableColumnMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/mapper/GenTableMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/GenTableServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/service/IGenTableService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/GenUtils.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/VelocityInitializer.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/VelocityUtils.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/java/org/dromara/generator/util/VelocityUtils2.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/.DS_Store
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/generator.yml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/mapper/package-info.md
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/.DS_Store
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/bo.java.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/controller.java.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/domain.java.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/service.java.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/vo.java.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/soy/api/api.ts.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/soy/index-tree.vue.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/soy/index.vue.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/soy/modules/operate-drawer.vue.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/soy/modules/search.vue.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/soy/typings/api.d.ts.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/oracle/sql.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/postgres/sql.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/sql.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/sql/sqlserver/sql.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/ts/api.ts.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/ts/types.ts.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-job/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-job/pom.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/entity/BillDto.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/package-info.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/AlipayBillTask.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/SummaryBillTask.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/TestAnnoJobExecutor.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/TestBroadcastJob.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/TestClassJobExecutor.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/TestMapJobAnnotation.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/TestMapReduceAnnotation1.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/TestStaticShardingJob.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-job/src/main/java/org/dromara/job/snailjob/WechatBillTask.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/pom.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/readMe.md
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/.DS_Store
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/.DS_Store
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/.DS_Store
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/controller/HoisterTimeDataController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/controller/PackerTimeDataController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/controller/RollerTimeDataController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/domain/BoxTimeData.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/domain/FeedmatchTimeData.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/domain/HoisterTimeData.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/domain/MakeupTimeData.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/domain/PackerTimeData.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/domain/RollerTimeData.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/domain/TransTimeData.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/domain/bo/HoisterTimeDataBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/domain/bo/PackerTimeDataBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/domain/bo/RollerTimeDataBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/domain/vo/HoisterTimeDataVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/domain/vo/PackerTimeDataVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/domain/vo/RollerTimeDataVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/mapper/HoisterTimeDataMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/mapper/PackerTimeDataMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/mapper/RollerTimeDataMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/service/IHoisterTimeDataService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/service/IPackerTimeDataService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/service/IRollerTimeDataService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/service/impl/HoisterTimeDataServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/service/impl/PackerTimeDataServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/java/org/dromara/qa/service/impl/RollerTimeDataServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/resources/mapper/qa/PackerTimeDataMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-qa/src/main/resources/mapper/qa/RollerTimeDataMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/pom.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/CacheController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/SysLogininforController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/SysOperlogController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/monitor/SysUserOnlineController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysClientController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysConfigController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDeptController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDictDataController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysDictTypeController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysMenuController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysNoticeController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssConfigController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysOssController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysPostController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysProfileController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysRoleController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysSocialController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysTenantPackageController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/controller/system/SysUserController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysCache.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysClient.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysConfig.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDept.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDictData.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysDictType.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysLogininfor.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysMenu.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysNotice.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysOperLog.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysOss.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysOssConfig.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysOssExt.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysPost.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysRole.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysRoleDept.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysRoleMenu.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysSocial.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenant.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysTenantPackage.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUser.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUserOnline.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUserPost.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/SysUserRole.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysClientBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysConfigBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysDeptBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysDictDataBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysDictTypeBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysLogininforBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysMenuBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysNoticeBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysOperLogBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysOssBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysOssConfigBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysPostBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysRoleBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysSocialBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysTenantBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysTenantPackageBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserPasswordBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/bo/SysUserProfileBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/MetaVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/ProfileUserVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/RouterVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysClientVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysConfigVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysDeptVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysDictDataVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysDictTypeVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysLogininforVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysMenuVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysNoticeVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOperLogVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOssConfigVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOssUploadVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysOssVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysPostVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysRoleVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysSocialVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysTenantPackageVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysTenantVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserExportVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserImportVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserInfoVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/SysUserVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/domain/vo/UserInfoVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/listener/SysUserImportListener.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysClientMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysConfigMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDeptMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDictDataMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysDictTypeMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysLogininforMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysMenuMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysNoticeMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysOperLogMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysOssConfigMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysOssMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysPostMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysRoleDeptMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysRoleMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysRoleMenuMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysSocialMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysTenantMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysTenantPackageMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserPostMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/mapper/SysUserRoleMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/runner/SystemApplicationRunner.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysClientService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysConfigService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDataScopeService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDeptService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDictDataService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysDictTypeService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysLogininforService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysMenuService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysNoticeService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOperLogService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssConfigService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysOssService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysPermissionService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysPostService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysRoleService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysSocialService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysTenantPackageService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysTenantService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/ISysUserService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysClientServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysConfigServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDataScopeServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDeptServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictDataServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysDictTypeServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysLogininforServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysMenuServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysNoticeServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOperLogServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssConfigServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysOssServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPermissionServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysPostServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysRoleServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysSensitiveServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysSocialServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTaskAssigneeServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantPackageServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysTenantServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/package-info.md
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysClientMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysOssConfigMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysOssMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysSocialMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysTenantMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysTenantPackageMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/.flattened-pom.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/pom.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/ConditionalOnEnable.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/constant/FlowConstant.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/ButtonPermissionEnum.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/CopySettingEnum.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/MessageTypeEnum.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/NodeExtEnum.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeEnum.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskAssigneeType.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/TaskStatusEnum.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/common/enums/VariablesEnum.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/config/WarmFlowConfig.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwCategoryController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwDefinitionController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwInstanceController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwSpelController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/FlwTaskController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/controller/TestLeaveController.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/FlowCategory.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/FlowInstanceBizExt.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/FlowSpel.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/TestLeave.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/BackProcessBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/CompleteTaskBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCancelBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCategoryBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowCopyBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInstanceBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowInvalidBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowNextNodeBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowSpelBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowTaskBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowTerminationBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowUrgeTaskBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/FlowVariableBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/StartProcessBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TaskOperationBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/bo/TestLeaveBo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/ButtonPermissionVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowCategoryVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowCopyVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowDefinitionVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowHisTaskVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowInstanceVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowSpelVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/FlowTaskVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/NodeExtVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/domain/vo/TestLeaveVo.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/FlowProcessEventHandler.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/handler/WorkflowPermissionHandler.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/listener/WorkflowGlobalListener.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwCategoryMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwInstanceBizExtMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwInstanceMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwSpelMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/FlwTaskMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/mapper/TestLeaveMapper.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/rule/SpelRuleComponent.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwCategoryService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwCommonService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwDefinitionService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwInstanceService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwNodeExtService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwSpelService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskAssigneeService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/IFlwTaskService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/ITestLeaveService.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/CategoryNameTranslationImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCategoryServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwChartExtServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwCommonServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwDefinitionServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwInstanceServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwNodeExtServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwSpelServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskAssigneeServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/FlwTaskServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/TestLeaveServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/java/org/dromara/workflow/service/impl/WorkflowServiceImpl.java
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/package-info.md
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwCategoryMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwInstanceBizExtMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwInstanceMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwSpelMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/FlwTaskMapper.xml
RuoYi-Vue-Plus/ruoyi-modules/ruoyi-workflow/src/main/resources/mapper/workflow/TestLeaveMapper.xml
RuoYi-Vue-Plus/script/bin/ry.bat
RuoYi-Vue-Plus/script/bin/ry.sh
RuoYi-Vue-Plus/script/docker/database.yml
RuoYi-Vue-Plus/script/docker/docker-compose.yml
RuoYi-Vue-Plus/script/docker/nginx/conf/nginx.conf
RuoYi-Vue-Plus/script/docker/redis/conf/redis.conf
RuoYi-Vue-Plus/script/docker/redis/data/README.md
RuoYi-Vue-Plus/script/leave/leave1.json
RuoYi-Vue-Plus/script/leave/leave2.json
RuoYi-Vue-Plus/script/leave/leave3.json
RuoYi-Vue-Plus/script/leave/leave4.json
RuoYi-Vue-Plus/script/leave/leave5.json
RuoYi-Vue-Plus/script/leave/leave6.json
RuoYi-Vue-Plus/script/sql/oracle/oracle_ry_job.sql
RuoYi-Vue-Plus/script/sql/oracle/oracle_ry_vue_5.X.sql
RuoYi-Vue-Plus/script/sql/oracle/oracle_ry_workflow.sql
RuoYi-Vue-Plus/script/sql/postgres/postgres_ry_job.sql
RuoYi-Vue-Plus/script/sql/postgres/postgres_ry_vue_5.X.sql
RuoYi-Vue-Plus/script/sql/postgres/postgres_ry_workflow.sql
RuoYi-Vue-Plus/script/sql/ry_job.sql
RuoYi-Vue-Plus/script/sql/ry_vue_5.X.sql
RuoYi-Vue-Plus/script/sql/ry_workflow.sql
RuoYi-Vue-Plus/script/sql/sqlserver/sqlserver_ry_job.sql
RuoYi-Vue-Plus/script/sql/sqlserver/sqlserver_ry_vue_5.X.sql
RuoYi-Vue-Plus/script/sql/sqlserver/sqlserver_ry_workflow.sql
RuoYi-Vue-Plus/script/sql/update/oracle/update_5.0-5.1.sql
RuoYi-Vue-Plus/script/sql/update/oracle/update_5.1.0-5.1.1.sql
RuoYi-Vue-Plus/script/sql/update/oracle/update_5.1.1-5.1.2.sql
RuoYi-Vue-Plus/script/sql/update/oracle/update_5.1.2-5.2.0.sql
RuoYi-Vue-Plus/script/sql/update/oracle/update_5.3.0-5.3.1.sql
RuoYi-Vue-Plus/script/sql/update/oracle/update_5.3.1-5.4.0.sql
RuoYi-Vue-Plus/script/sql/update/oracle/update_5.4.1-5.5.0.sql
RuoYi-Vue-Plus/script/sql/update/oracle/update_5.5.0-5.5.1.sql
RuoYi-Vue-Plus/script/sql/update/oracle/update_5.5.1-5.5.2.sql
RuoYi-Vue-Plus/script/sql/update/postgres/update_5.0-5.1.sql
RuoYi-Vue-Plus/script/sql/update/postgres/update_5.1.0-5.1.1.sql
RuoYi-Vue-Plus/script/sql/update/postgres/update_5.1.1-5.1.2.sql
RuoYi-Vue-Plus/script/sql/update/postgres/update_5.1.2-5.2.0.sql
RuoYi-Vue-Plus/script/sql/update/postgres/update_5.3.0-5.3.1.sql
RuoYi-Vue-Plus/script/sql/update/postgres/update_5.3.1-5.4.0.sql
RuoYi-Vue-Plus/script/sql/update/postgres/update_5.4.1-5.5.0.sql
RuoYi-Vue-Plus/script/sql/update/postgres/update_5.5.0-5.5.1.sql
RuoYi-Vue-Plus/script/sql/update/postgres/update_5.5.1-5.5.2.sql
RuoYi-Vue-Plus/script/sql/update/sqlserver/update_5.0-5.1.sql
RuoYi-Vue-Plus/script/sql/update/sqlserver/update_5.1.0-5.1.1.sql
RuoYi-Vue-Plus/script/sql/update/sqlserver/update_5.1.1-5.1.2.sql
RuoYi-Vue-Plus/script/sql/update/sqlserver/update_5.1.2-5.2.0.sql
RuoYi-Vue-Plus/script/sql/update/sqlserver/update_5.3.0-5.3.1.sql
RuoYi-Vue-Plus/script/sql/update/sqlserver/update_5.3.1-5.4.0.sql
RuoYi-Vue-Plus/script/sql/update/sqlserver/update_5.4.1-5.5.0.sql
RuoYi-Vue-Plus/script/sql/update/sqlserver/update_5.5.0-5.5.1.sql
RuoYi-Vue-Plus/script/sql/update/sqlserver/update_5.5.1-5.5.2.sql
RuoYi-Vue-Plus/script/sql/update/update_5.0-5.1.sql
RuoYi-Vue-Plus/script/sql/update/update_5.1.0-5.1.1.sql
RuoYi-Vue-Plus/script/sql/update/update_5.1.1-5.1.2.sql
RuoYi-Vue-Plus/script/sql/update/update_5.1.2-5.2.0.sql
RuoYi-Vue-Plus/script/sql/update/update_5.3.0-5.3.1.sql
RuoYi-Vue-Plus/script/sql/update/update_5.3.1-5.4.0.sql
RuoYi-Vue-Plus/script/sql/update/update_5.4.1-5.5.0.sql
RuoYi-Vue-Plus/script/sql/update/update_5.5.0-5.5.1.sql
RuoYi-Vue-Plus/script/sql/update/update_5.5.1-5.5.2.sql
RuoYi-Vue-Plus/开发日志.md
ruoyi-plus-soybean/.drone.yml
ruoyi-plus-soybean/.editorconfig
ruoyi-plus-soybean/.env
ruoyi-plus-soybean/.env.dev
ruoyi-plus-soybean/.env.prod
ruoyi-plus-soybean/.env.test
ruoyi-plus-soybean/.gitattributes
ruoyi-plus-soybean/.gitignore
ruoyi-plus-soybean/.npmrc
ruoyi-plus-soybean/CHANGELOG.md
ruoyi-plus-soybean/LICENSE
ruoyi-plus-soybean/README.md
ruoyi-plus-soybean/build/config/index.ts
ruoyi-plus-soybean/build/config/proxy.ts
ruoyi-plus-soybean/build/config/time.ts
ruoyi-plus-soybean/build/plugins/devtools.ts
ruoyi-plus-soybean/build/plugins/html.ts
ruoyi-plus-soybean/build/plugins/index.ts
ruoyi-plus-soybean/build/plugins/router.ts
ruoyi-plus-soybean/build/plugins/unocss.ts
ruoyi-plus-soybean/build/plugins/unplugin.ts
ruoyi-plus-soybean/docs/README.md
ruoyi-plus-soybean/docs/java/VelocityUtils.java
ruoyi-plus-soybean/docs/sql/sys_dict_data.sql
ruoyi-plus-soybean/docs/sql/sys_menu.sql
ruoyi-plus-soybean/docs/template/api/api.ts.vm
ruoyi-plus-soybean/docs/template/index-tree.vue.vm
ruoyi-plus-soybean/docs/template/index.vue.vm
ruoyi-plus-soybean/docs/template/modules/operate-drawer.vue.vm
ruoyi-plus-soybean/docs/template/modules/search.vue.vm
ruoyi-plus-soybean/docs/template/typings/api.d.ts.vm
ruoyi-plus-soybean/eslint.config.js
ruoyi-plus-soybean/index.html
ruoyi-plus-soybean/package.json
ruoyi-plus-soybean/packages/alova/package.json
ruoyi-plus-soybean/packages/alova/src/client.ts
ruoyi-plus-soybean/packages/alova/src/constant.ts
ruoyi-plus-soybean/packages/alova/src/fetch.ts
ruoyi-plus-soybean/packages/alova/src/index.ts
ruoyi-plus-soybean/packages/alova/src/mock.ts
ruoyi-plus-soybean/packages/alova/src/type.ts
ruoyi-plus-soybean/packages/alova/tsconfig.json
ruoyi-plus-soybean/packages/axios/package.json
ruoyi-plus-soybean/packages/axios/src/constant.ts
ruoyi-plus-soybean/packages/axios/src/index.ts
ruoyi-plus-soybean/packages/axios/src/options.ts
ruoyi-plus-soybean/packages/axios/src/shared.ts
ruoyi-plus-soybean/packages/axios/src/type.ts
ruoyi-plus-soybean/packages/axios/tsconfig.json
ruoyi-plus-soybean/packages/color/package.json
ruoyi-plus-soybean/packages/color/src/constant/index.ts
ruoyi-plus-soybean/packages/color/src/constant/name.ts
ruoyi-plus-soybean/packages/color/src/constant/palette.ts
ruoyi-plus-soybean/packages/color/src/index.ts
ruoyi-plus-soybean/packages/color/src/palette/antd.ts
ruoyi-plus-soybean/packages/color/src/palette/index.ts
ruoyi-plus-soybean/packages/color/src/palette/recommend.ts
ruoyi-plus-soybean/packages/color/src/shared/colord.ts
ruoyi-plus-soybean/packages/color/src/shared/index.ts
ruoyi-plus-soybean/packages/color/src/shared/name.ts
ruoyi-plus-soybean/packages/color/src/types/index.ts
ruoyi-plus-soybean/packages/color/tsconfig.json
ruoyi-plus-soybean/packages/hooks/package.json
ruoyi-plus-soybean/packages/hooks/src/index.ts
ruoyi-plus-soybean/packages/hooks/src/use-boolean.ts
ruoyi-plus-soybean/packages/hooks/src/use-context.ts
ruoyi-plus-soybean/packages/hooks/src/use-count-down.ts
ruoyi-plus-soybean/packages/hooks/src/use-loading.ts
ruoyi-plus-soybean/packages/hooks/src/use-request.ts
ruoyi-plus-soybean/packages/hooks/src/use-svg-icon-render.ts
ruoyi-plus-soybean/packages/hooks/src/use-table.ts
ruoyi-plus-soybean/packages/hooks/tsconfig.json
ruoyi-plus-soybean/packages/materials/package.json
ruoyi-plus-soybean/packages/materials/src/index.ts
ruoyi-plus-soybean/packages/materials/src/libs/admin-layout/index.module.css
ruoyi-plus-soybean/packages/materials/src/libs/admin-layout/index.module.css.d.ts
ruoyi-plus-soybean/packages/materials/src/libs/admin-layout/index.ts
ruoyi-plus-soybean/packages/materials/src/libs/admin-layout/index.vue
ruoyi-plus-soybean/packages/materials/src/libs/admin-layout/shared.ts
ruoyi-plus-soybean/packages/materials/src/libs/page-tab/button-tab.vue
ruoyi-plus-soybean/packages/materials/src/libs/page-tab/chrome-tab-bg.vue
ruoyi-plus-soybean/packages/materials/src/libs/page-tab/chrome-tab.vue
ruoyi-plus-soybean/packages/materials/src/libs/page-tab/index.module.css
ruoyi-plus-soybean/packages/materials/src/libs/page-tab/index.module.css.d.ts
ruoyi-plus-soybean/packages/materials/src/libs/page-tab/index.ts
ruoyi-plus-soybean/packages/materials/src/libs/page-tab/index.vue
ruoyi-plus-soybean/packages/materials/src/libs/page-tab/shared.ts
ruoyi-plus-soybean/packages/materials/src/libs/page-tab/slider-tab.vue
ruoyi-plus-soybean/packages/materials/src/libs/page-tab/svg-close.vue
ruoyi-plus-soybean/packages/materials/src/libs/simple-scrollbar/index.ts
ruoyi-plus-soybean/packages/materials/src/libs/simple-scrollbar/index.vue
ruoyi-plus-soybean/packages/materials/src/types/index.ts
ruoyi-plus-soybean/packages/materials/tsconfig.json
ruoyi-plus-soybean/packages/scripts/bin.ts
ruoyi-plus-soybean/packages/scripts/package.json
ruoyi-plus-soybean/packages/scripts/src/commands/changelog.ts
ruoyi-plus-soybean/packages/scripts/src/commands/cleanup.ts
ruoyi-plus-soybean/packages/scripts/src/commands/git-commit.ts
ruoyi-plus-soybean/packages/scripts/src/commands/index.ts
ruoyi-plus-soybean/packages/scripts/src/commands/release.ts
ruoyi-plus-soybean/packages/scripts/src/commands/router.ts
ruoyi-plus-soybean/packages/scripts/src/commands/update-pkg.ts
ruoyi-plus-soybean/packages/scripts/src/config/index.ts
ruoyi-plus-soybean/packages/scripts/src/index.ts
ruoyi-plus-soybean/packages/scripts/src/locales/index.ts
ruoyi-plus-soybean/packages/scripts/src/shared/index.ts
ruoyi-plus-soybean/packages/scripts/src/types/index.ts
ruoyi-plus-soybean/packages/scripts/tsconfig.json
ruoyi-plus-soybean/packages/uno-preset/package.json
ruoyi-plus-soybean/packages/uno-preset/src/index.ts
ruoyi-plus-soybean/packages/uno-preset/tsconfig.json
ruoyi-plus-soybean/packages/utils/package.json
ruoyi-plus-soybean/packages/utils/src/crypto.ts
ruoyi-plus-soybean/packages/utils/src/index.ts
ruoyi-plus-soybean/packages/utils/src/klona.ts
ruoyi-plus-soybean/packages/utils/src/nanoid.ts
ruoyi-plus-soybean/packages/utils/src/storage.ts
ruoyi-plus-soybean/packages/utils/tsconfig.json
ruoyi-plus-soybean/pnpm-lock.yaml
ruoyi-plus-soybean/pnpm-workspace.yaml
ruoyi-plus-soybean/public/favicon.svg
ruoyi-plus-soybean/public/streamsaver/mitm.html
ruoyi-plus-soybean/public/streamsaver/sw.js
ruoyi-plus-soybean/src/App.vue
ruoyi-plus-soybean/src/assets/imgs/soybean.jpg
ruoyi-plus-soybean/src/assets/svg-icon/activity.svg
ruoyi-plus-soybean/src/assets/svg-icon/at-sign.svg
ruoyi-plus-soybean/src/assets/svg-icon/avatar.svg
ruoyi-plus-soybean/src/assets/svg-icon/banner.svg
ruoyi-plus-soybean/src/assets/svg-icon/bell.svg
ruoyi-plus-soybean/src/assets/svg-icon/cast.svg
ruoyi-plus-soybean/src/assets/svg-icon/chrome.svg
ruoyi-plus-soybean/src/assets/svg-icon/copy.svg
ruoyi-plus-soybean/src/assets/svg-icon/custom-icon.svg
ruoyi-plus-soybean/src/assets/svg-icon/empty-data.svg
ruoyi-plus-soybean/src/assets/svg-icon/expectation.svg
ruoyi-plus-soybean/src/assets/svg-icon/heart.svg
ruoyi-plus-soybean/src/assets/svg-icon/login-background.svg
ruoyi-plus-soybean/src/assets/svg-icon/logo.svg
ruoyi-plus-soybean/src/assets/svg-icon/maxkey.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/404.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/bug.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/build.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/button.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/caret-back.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/caret-forward.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/cascader.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/category.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/chart.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/checkbox.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/clipboard.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/code.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/color.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/company.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/component.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/dashboard.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/date-range.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/date.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/dict.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/documentation.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/download.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/drag.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/druid.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/edit.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/education.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/email.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/example.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/excel.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/exit-fullscreen.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/eye-open.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/eye.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/finish.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/form.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/fullscreen.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/gitee.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/github.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/guide.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/icon.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/input.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/international.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/job.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/language.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/link.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/list.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/lock.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/log.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/logininfor.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/message.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/model.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/money.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/monitor.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/my-copy.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/my-task.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/nested.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/number.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/online.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/password.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/pdf.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/people.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/peoples.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/phone.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/post.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/process-definition.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/qq.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/question.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/radio.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/rate.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/redis-list.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/redis.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/row.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/search.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/select.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/server.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/shopping.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/size.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/skill.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/slider.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/star.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/swagger.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/switch.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/system.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/tab.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/table.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/textarea.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/theme.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/time-range.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/time.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/tool.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/tree-table.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/tree.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/upload.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/user.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/validCode.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/waiting.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/wechat.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/workflow.svg
ruoyi-plus-soybean/src/assets/svg-icon/menu/zip.svg
ruoyi-plus-soybean/src/assets/svg-icon/network-error.svg
ruoyi-plus-soybean/src/assets/svg-icon/no-icon.svg
ruoyi-plus-soybean/src/assets/svg-icon/no-permission.svg
ruoyi-plus-soybean/src/assets/svg-icon/not-found.svg
ruoyi-plus-soybean/src/assets/svg-icon/service-error.svg
ruoyi-plus-soybean/src/assets/svg-icon/topiam.svg
ruoyi-plus-soybean/src/assets/svg-icon/wind.svg
ruoyi-plus-soybean/src/components/advanced/table-column-setting.vue
ruoyi-plus-soybean/src/components/advanced/table-header-operation.vue
ruoyi-plus-soybean/src/components/advanced/table-row-check-alert.vue
ruoyi-plus-soybean/src/components/advanced/table-sider-layout.vue
ruoyi-plus-soybean/src/components/common/app-provider.vue
ruoyi-plus-soybean/src/components/common/dark-mode-container.vue
ruoyi-plus-soybean/src/components/common/data-table.vue
ruoyi-plus-soybean/src/components/common/exception-base.vue
ruoyi-plus-soybean/src/components/common/full-screen.vue
ruoyi-plus-soybean/src/components/common/icon-tooltip.vue
ruoyi-plus-soybean/src/components/common/lang-switch.vue
ruoyi-plus-soybean/src/components/common/menu-toggler.vue
ruoyi-plus-soybean/src/components/common/pin-toggler.vue
ruoyi-plus-soybean/src/components/common/reload-button.vue
ruoyi-plus-soybean/src/components/common/system-logo.vue
ruoyi-plus-soybean/src/components/common/theme-schema-switch.vue
ruoyi-plus-soybean/src/components/custom/better-scroll.vue
ruoyi-plus-soybean/src/components/custom/boolean-tag.vue
ruoyi-plus-soybean/src/components/custom/button-icon.vue
ruoyi-plus-soybean/src/components/custom/count-to.vue
ruoyi-plus-soybean/src/components/custom/dept-tree-select.vue
ruoyi-plus-soybean/src/components/custom/dept-tree.vue
ruoyi-plus-soybean/src/components/custom/dict-checkbox.vue
ruoyi-plus-soybean/src/components/custom/dict-radio.vue
ruoyi-plus-soybean/src/components/custom/dict-select.vue
ruoyi-plus-soybean/src/components/custom/dict-tag.vue
ruoyi-plus-soybean/src/components/custom/file-upload.vue
ruoyi-plus-soybean/src/components/custom/form-tip.vue
ruoyi-plus-soybean/src/components/custom/json-preview.vue
ruoyi-plus-soybean/src/components/custom/look-forward.vue
ruoyi-plus-soybean/src/components/custom/menu-tree-select.vue
ruoyi-plus-soybean/src/components/custom/menu-tree.vue
ruoyi-plus-soybean/src/components/custom/oss-upload.vue
ruoyi-plus-soybean/src/components/custom/post-select.vue
ruoyi-plus-soybean/src/components/custom/role-select.vue
ruoyi-plus-soybean/src/components/custom/soybean-avatar.vue
ruoyi-plus-soybean/src/components/custom/status-switch.vue
ruoyi-plus-soybean/src/components/custom/svg-icon.vue
ruoyi-plus-soybean/src/components/custom/tenant-select.vue
ruoyi-plus-soybean/src/components/custom/umo-doc-editor.vue
ruoyi-plus-soybean/src/components/custom/user-select.vue
ruoyi-plus-soybean/src/components/custom/wave-bg.vue
ruoyi-plus-soybean/src/constants/app.ts
ruoyi-plus-soybean/src/constants/business.ts
ruoyi-plus-soybean/src/constants/common.ts
ruoyi-plus-soybean/src/constants/reg.ts
ruoyi-plus-soybean/src/enum/business.ts
ruoyi-plus-soybean/src/enum/index.ts
ruoyi-plus-soybean/src/hooks/business/auth.ts
ruoyi-plus-soybean/src/hooks/business/captcha.ts
ruoyi-plus-soybean/src/hooks/business/dict.ts
ruoyi-plus-soybean/src/hooks/business/download.ts
ruoyi-plus-soybean/src/hooks/common/echarts.ts
ruoyi-plus-soybean/src/hooks/common/form.ts
ruoyi-plus-soybean/src/hooks/common/icon.ts
ruoyi-plus-soybean/src/hooks/common/loading.ts
ruoyi-plus-soybean/src/hooks/common/router.ts
ruoyi-plus-soybean/src/hooks/common/table.ts
ruoyi-plus-soybean/src/layouts/base-layout/index.vue
ruoyi-plus-soybean/src/layouts/blank-layout/index.vue
ruoyi-plus-soybean/src/layouts/modules/global-breadcrumb/index.vue
ruoyi-plus-soybean/src/layouts/modules/global-content/index.vue
ruoyi-plus-soybean/src/layouts/modules/global-footer/index.vue
ruoyi-plus-soybean/src/layouts/modules/global-header/components/message-button.vue
ruoyi-plus-soybean/src/layouts/modules/global-header/components/theme-button.vue
ruoyi-plus-soybean/src/layouts/modules/global-header/components/user-avatar.vue
ruoyi-plus-soybean/src/layouts/modules/global-header/index.vue
ruoyi-plus-soybean/src/layouts/modules/global-logo/index.vue
ruoyi-plus-soybean/src/layouts/modules/global-menu/components/first-level-menu.vue
ruoyi-plus-soybean/src/layouts/modules/global-menu/context/index.ts
ruoyi-plus-soybean/src/layouts/modules/global-menu/index.vue
ruoyi-plus-soybean/src/layouts/modules/global-menu/modules/horizontal-menu.vue
ruoyi-plus-soybean/src/layouts/modules/global-menu/modules/top-hybrid-header-first.vue
ruoyi-plus-soybean/src/layouts/modules/global-menu/modules/top-hybrid-sidebar-first.vue
ruoyi-plus-soybean/src/layouts/modules/global-menu/modules/vertical-hybrid-header-first.vue
ruoyi-plus-soybean/src/layouts/modules/global-menu/modules/vertical-menu.vue
ruoyi-plus-soybean/src/layouts/modules/global-menu/modules/vertical-mix-menu.vue
ruoyi-plus-soybean/src/layouts/modules/global-search/components/search-footer.vue
ruoyi-plus-soybean/src/layouts/modules/global-search/components/search-modal.vue
ruoyi-plus-soybean/src/layouts/modules/global-search/components/search-result.vue
ruoyi-plus-soybean/src/layouts/modules/global-search/index.vue
ruoyi-plus-soybean/src/layouts/modules/global-sider/index.vue
ruoyi-plus-soybean/src/layouts/modules/global-tab/context-menu.vue
ruoyi-plus-soybean/src/layouts/modules/global-tab/index.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/components/layout-mode-card.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/components/setting-item.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/index.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/modules/appearance/index.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/modules/appearance/modules/theme-color.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/modules/appearance/modules/theme-radius.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/modules/appearance/modules/theme-schema.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/modules/config-operation.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/modules/general/index.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/modules/general/modules/global-settings.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/modules/general/modules/watermark-settings.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/modules/layout/index.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/modules/layout/modules/content-settings.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/modules/layout/modules/footer-settings.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/modules/layout/modules/header-settings.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/modules/layout/modules/layout-mode.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/modules/layout/modules/sider-settings.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/modules/layout/modules/tab-settings.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/modules/layout/modules/table-settings.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/modules/preset/index.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/modules/preset/modules/theme-preset.vue
ruoyi-plus-soybean/src/layouts/modules/theme-drawer/modules/table-props.vue
ruoyi-plus-soybean/src/locales/dayjs.ts
ruoyi-plus-soybean/src/locales/index.ts
ruoyi-plus-soybean/src/locales/langs/en-us.ts
ruoyi-plus-soybean/src/locales/langs/zh-cn.ts
ruoyi-plus-soybean/src/locales/locale.ts
ruoyi-plus-soybean/src/locales/naive.ts
ruoyi-plus-soybean/src/main.ts
ruoyi-plus-soybean/src/plugins/app.ts
ruoyi-plus-soybean/src/plugins/assets.ts
ruoyi-plus-soybean/src/plugins/dayjs.ts
ruoyi-plus-soybean/src/plugins/iconify.ts
ruoyi-plus-soybean/src/plugins/index.ts
ruoyi-plus-soybean/src/plugins/loading.ts
ruoyi-plus-soybean/src/plugins/nprogress.ts
ruoyi-plus-soybean/src/router/elegant/imports.ts
ruoyi-plus-soybean/src/router/elegant/routes.ts
ruoyi-plus-soybean/src/router/elegant/transform.ts
ruoyi-plus-soybean/src/router/guard/index.ts
ruoyi-plus-soybean/src/router/guard/progress.ts
ruoyi-plus-soybean/src/router/guard/route.ts
ruoyi-plus-soybean/src/router/guard/title.ts
ruoyi-plus-soybean/src/router/index.ts
ruoyi-plus-soybean/src/router/routes/builtin.ts
ruoyi-plus-soybean/src/router/routes/index.ts
ruoyi-plus-soybean/src/service/api/analy/hoister-data.ts
ruoyi-plus-soybean/src/service/api/analy/packer-data.ts
ruoyi-plus-soybean/src/service/api/analy/roller-data.ts
ruoyi-plus-soybean/src/service/api/auth.ts
ruoyi-plus-soybean/src/service/api/demo/demo.ts
ruoyi-plus-soybean/src/service/api/demo/index.ts
ruoyi-plus-soybean/src/service/api/demo/tree.ts
ruoyi-plus-soybean/src/service/api/index.ts
ruoyi-plus-soybean/src/service/api/monitor/cache.ts
ruoyi-plus-soybean/src/service/api/monitor/index.ts
ruoyi-plus-soybean/src/service/api/monitor/login-infor.ts
ruoyi-plus-soybean/src/service/api/monitor/online.ts
ruoyi-plus-soybean/src/service/api/monitor/oper-log.ts
ruoyi-plus-soybean/src/service/api/route.ts
ruoyi-plus-soybean/src/service/api/system/client.ts
ruoyi-plus-soybean/src/service/api/system/config.ts
ruoyi-plus-soybean/src/service/api/system/dept.ts
ruoyi-plus-soybean/src/service/api/system/dict-data.ts
ruoyi-plus-soybean/src/service/api/system/dict.ts
ruoyi-plus-soybean/src/service/api/system/index.ts
ruoyi-plus-soybean/src/service/api/system/menu.ts
ruoyi-plus-soybean/src/service/api/system/notice.ts
ruoyi-plus-soybean/src/service/api/system/oss-config.ts
ruoyi-plus-soybean/src/service/api/system/oss.ts
ruoyi-plus-soybean/src/service/api/system/post.ts
ruoyi-plus-soybean/src/service/api/system/role.ts
ruoyi-plus-soybean/src/service/api/system/social.ts
ruoyi-plus-soybean/src/service/api/system/tenant-package.ts
ruoyi-plus-soybean/src/service/api/system/tenant.ts
ruoyi-plus-soybean/src/service/api/system/user.ts
ruoyi-plus-soybean/src/service/api/tool/gen.ts
ruoyi-plus-soybean/src/service/api/tool/index.ts
ruoyi-plus-soybean/src/service/request/index.ts
ruoyi-plus-soybean/src/service/request/shared.ts
ruoyi-plus-soybean/src/service/request/type.ts
ruoyi-plus-soybean/src/store/index.ts
ruoyi-plus-soybean/src/store/modules/app/index.ts
ruoyi-plus-soybean/src/store/modules/auth/index.ts
ruoyi-plus-soybean/src/store/modules/auth/shared.ts
ruoyi-plus-soybean/src/store/modules/dict/index.ts
ruoyi-plus-soybean/src/store/modules/notice/index.ts
ruoyi-plus-soybean/src/store/modules/route/index.ts
ruoyi-plus-soybean/src/store/modules/route/shared.ts
ruoyi-plus-soybean/src/store/modules/tab/index.ts
ruoyi-plus-soybean/src/store/modules/tab/shared.ts
ruoyi-plus-soybean/src/store/modules/theme/index.ts
ruoyi-plus-soybean/src/store/modules/theme/shared.ts
ruoyi-plus-soybean/src/store/plugins/index.ts
ruoyi-plus-soybean/src/styles/css/global.css
ruoyi-plus-soybean/src/styles/css/nprogress.css
ruoyi-plus-soybean/src/styles/css/reset.css
ruoyi-plus-soybean/src/styles/css/transition.css
ruoyi-plus-soybean/src/styles/scss/custom.scss
ruoyi-plus-soybean/src/styles/scss/global.scss
ruoyi-plus-soybean/src/styles/scss/loading.scss
ruoyi-plus-soybean/src/styles/scss/scrollbar.scss
ruoyi-plus-soybean/src/theme/preset/azir.json
ruoyi-plus-soybean/src/theme/preset/compact.json
ruoyi-plus-soybean/src/theme/preset/dark.json
ruoyi-plus-soybean/src/theme/preset/default.json
ruoyi-plus-soybean/src/theme/preset/soybean.json
ruoyi-plus-soybean/src/theme/settings.ts
ruoyi-plus-soybean/src/theme/vars.ts
ruoyi-plus-soybean/src/typings/api/analy.hoister-data.api.d.ts
ruoyi-plus-soybean/src/typings/api/analy.packer-data.api.d.ts
ruoyi-plus-soybean/src/typings/api/analy.roller-data.api.d.ts
ruoyi-plus-soybean/src/typings/api/api.d.ts
ruoyi-plus-soybean/src/typings/api/auth.d.ts
ruoyi-plus-soybean/src/typings/api/demo.api.d.ts
ruoyi-plus-soybean/src/typings/api/monitor.api.d.ts
ruoyi-plus-soybean/src/typings/api/route.d.ts
ruoyi-plus-soybean/src/typings/api/system.api.d.ts
ruoyi-plus-soybean/src/typings/api/tool.api.d.ts
ruoyi-plus-soybean/src/typings/app.d.ts
ruoyi-plus-soybean/src/typings/common.d.ts
ruoyi-plus-soybean/src/typings/components.d.ts
ruoyi-plus-soybean/src/typings/elegant-router.d.ts
ruoyi-plus-soybean/src/typings/global.d.ts
ruoyi-plus-soybean/src/typings/naive-ui.d.ts
ruoyi-plus-soybean/src/typings/router.d.ts
ruoyi-plus-soybean/src/typings/storage.d.ts
ruoyi-plus-soybean/src/typings/union-key.d.ts
ruoyi-plus-soybean/src/typings/vite-env.d.ts
ruoyi-plus-soybean/src/utils/agent.ts
ruoyi-plus-soybean/src/utils/common.ts
ruoyi-plus-soybean/src/utils/copy.ts
ruoyi-plus-soybean/src/utils/crypto.ts
ruoyi-plus-soybean/src/utils/icon-tag-format.ts
ruoyi-plus-soybean/src/utils/icon.ts
ruoyi-plus-soybean/src/utils/jsencrypt.ts
ruoyi-plus-soybean/src/utils/service.ts
ruoyi-plus-soybean/src/utils/sse.ts
ruoyi-plus-soybean/src/utils/storage.ts
ruoyi-plus-soybean/src/utils/websocket.ts
ruoyi-plus-soybean/src/views/_builtin/403/index.vue
ruoyi-plus-soybean/src/views/_builtin/404/index.vue
ruoyi-plus-soybean/src/views/_builtin/500/index.vue
ruoyi-plus-soybean/src/views/_builtin/iframe-page/[url].vue
ruoyi-plus-soybean/src/views/_builtin/login/index.vue
ruoyi-plus-soybean/src/views/_builtin/login/modules/bind-wechat.vue
ruoyi-plus-soybean/src/views/_builtin/login/modules/code-login.vue
ruoyi-plus-soybean/src/views/_builtin/login/modules/pwd-login.vue
ruoyi-plus-soybean/src/views/_builtin/login/modules/register.vue
ruoyi-plus-soybean/src/views/_builtin/login/modules/reset-pwd.vue
ruoyi-plus-soybean/src/views/_builtin/social-callback/index.vue
ruoyi-plus-soybean/src/views/_builtin/user-center/index.vue
ruoyi-plus-soybean/src/views/_builtin/user-center/modules/online-table.vue
ruoyi-plus-soybean/src/views/_builtin/user-center/modules/social-card.vue
ruoyi-plus-soybean/src/views/_builtin/user-center/modules/user-avatar.vue
ruoyi-plus-soybean/src/views/about/index.vue
ruoyi-plus-soybean/src/views/analy/hoister/index.vue
ruoyi-plus-soybean/src/views/analy/hoister/modules/hoister-data-operate-drawer.vue
ruoyi-plus-soybean/src/views/analy/hoister/modules/hoister-data-search.vue
ruoyi-plus-soybean/src/views/analy/output-analy/index.vue
ruoyi-plus-soybean/src/views/analy/output-analy/modules/roller-data-line-chart.vue
ruoyi-plus-soybean/src/views/analy/output-analy/modules/roller-data-operate-drawer.vue
ruoyi-plus-soybean/src/views/analy/output-analy/modules/roller-data-search.vue
ruoyi-plus-soybean/src/views/analy/packer/index.vue
ruoyi-plus-soybean/src/views/analy/packer/modules/packer-data-operate-drawer.vue
ruoyi-plus-soybean/src/views/analy/packer/modules/packer-data-search.vue
ruoyi-plus-soybean/src/views/analy/roller/index.vue
ruoyi-plus-soybean/src/views/analy/roller/modules/roller-data-operate-drawer.vue
ruoyi-plus-soybean/src/views/analy/roller/modules/roller-data-search.vue
ruoyi-plus-soybean/src/views/demo/demo/index.vue
ruoyi-plus-soybean/src/views/demo/demo/modules/demo-operate-drawer.vue
ruoyi-plus-soybean/src/views/demo/demo/modules/demo-search.vue
ruoyi-plus-soybean/src/views/demo/tree/index.vue
ruoyi-plus-soybean/src/views/demo/tree/modules/tree-operate-drawer.vue
ruoyi-plus-soybean/src/views/demo/tree/modules/tree-search.vue
ruoyi-plus-soybean/src/views/home/index.vue
ruoyi-plus-soybean/src/views/home/modules/card-data.vue
ruoyi-plus-soybean/src/views/home/modules/creativity-banner.vue
ruoyi-plus-soybean/src/views/home/modules/header-banner.vue
ruoyi-plus-soybean/src/views/home/modules/line-chart.vue
ruoyi-plus-soybean/src/views/home/modules/pie-chart.vue
ruoyi-plus-soybean/src/views/home/modules/project-news.vue
ruoyi-plus-soybean/src/views/monitor/cache/index.vue
ruoyi-plus-soybean/src/views/monitor/logininfor/index.vue
ruoyi-plus-soybean/src/views/monitor/logininfor/modules/login-infor-search.vue
ruoyi-plus-soybean/src/views/monitor/logininfor/modules/login-infor-view-drawer.vue
ruoyi-plus-soybean/src/views/monitor/online/index.vue
ruoyi-plus-soybean/src/views/monitor/online/modules/online-search.vue
ruoyi-plus-soybean/src/views/monitor/operlog/index.vue
ruoyi-plus-soybean/src/views/monitor/operlog/modules/oper-log-search.vue
ruoyi-plus-soybean/src/views/monitor/operlog/modules/oper-log-view-drawer.vue
ruoyi-plus-soybean/src/views/system/client/index.vue
ruoyi-plus-soybean/src/views/system/client/modules/client-operate-drawer.vue
ruoyi-plus-soybean/src/views/system/client/modules/client-search.vue
ruoyi-plus-soybean/src/views/system/config/index.vue
ruoyi-plus-soybean/src/views/system/config/modules/config-operate-drawer.vue
ruoyi-plus-soybean/src/views/system/config/modules/config-search.vue
ruoyi-plus-soybean/src/views/system/dept/index.vue
ruoyi-plus-soybean/src/views/system/dept/modules/dept-operate-drawer.vue
ruoyi-plus-soybean/src/views/system/dept/modules/dept-search.vue
ruoyi-plus-soybean/src/views/system/dict/index.vue
ruoyi-plus-soybean/src/views/system/dict/modules/dict-data-operate-drawer.vue
ruoyi-plus-soybean/src/views/system/dict/modules/dict-data-search.vue
ruoyi-plus-soybean/src/views/system/dict/modules/dict-type-operate-drawer.vue
ruoyi-plus-soybean/src/views/system/menu/index.vue
ruoyi-plus-soybean/src/views/system/menu/modules/menu-cascade-delete-modal.vue
ruoyi-plus-soybean/src/views/system/menu/modules/menu-operate-drawer.vue
ruoyi-plus-soybean/src/views/system/notice/index.vue
ruoyi-plus-soybean/src/views/system/notice/modules/notice-operate-drawer.vue
ruoyi-plus-soybean/src/views/system/notice/modules/notice-search.vue
ruoyi-plus-soybean/src/views/system/oss-config/index.vue
ruoyi-plus-soybean/src/views/system/oss-config/modules/oss-config-operate-drawer.vue
ruoyi-plus-soybean/src/views/system/oss-config/modules/oss-config-search.vue
ruoyi-plus-soybean/src/views/system/oss/index.vue
ruoyi-plus-soybean/src/views/system/oss/modules/oss-search.vue
ruoyi-plus-soybean/src/views/system/oss/modules/oss-upload-modal.vue
ruoyi-plus-soybean/src/views/system/post/index.vue
ruoyi-plus-soybean/src/views/system/post/modules/post-operate-drawer.vue
ruoyi-plus-soybean/src/views/system/post/modules/post-search.vue
ruoyi-plus-soybean/src/views/system/role/index.vue
ruoyi-plus-soybean/src/views/system/role/modules/role-auth-user-drawer.vue
ruoyi-plus-soybean/src/views/system/role/modules/role-data-scope-drawer.vue
ruoyi-plus-soybean/src/views/system/role/modules/role-operate-drawer.vue
ruoyi-plus-soybean/src/views/system/role/modules/role-search.vue
ruoyi-plus-soybean/src/views/system/tenant-package/index.vue
ruoyi-plus-soybean/src/views/system/tenant-package/modules/tenant-package-operate-drawer.vue
ruoyi-plus-soybean/src/views/system/tenant-package/modules/tenant-package-search.vue
ruoyi-plus-soybean/src/views/system/tenant/index.vue
ruoyi-plus-soybean/src/views/system/tenant/modules/tenant-operate-drawer.vue
ruoyi-plus-soybean/src/views/system/tenant/modules/tenant-search.vue
ruoyi-plus-soybean/src/views/system/user/index.vue
ruoyi-plus-soybean/src/views/system/user/modules/user-import-modal.vue
ruoyi-plus-soybean/src/views/system/user/modules/user-operate-drawer.vue
ruoyi-plus-soybean/src/views/system/user/modules/user-password-drawer.vue
ruoyi-plus-soybean/src/views/system/user/modules/user-search.vue
ruoyi-plus-soybean/src/views/tool/gen/index.vue
ruoyi-plus-soybean/src/views/tool/gen/modules/gen-table-db-search.vue
ruoyi-plus-soybean/src/views/tool/gen/modules/gen-table-import-drawer.vue
ruoyi-plus-soybean/src/views/tool/gen/modules/gen-table-operate-drawer.vue
ruoyi-plus-soybean/src/views/tool/gen/modules/gen-table-preview-drawer.vue
ruoyi-plus-soybean/src/views/tool/gen/modules/gen-table-search.vue
ruoyi-plus-soybean/tsconfig.json
ruoyi-plus-soybean/uno.config.ts
ruoyi-plus-soybean/vite.config.ts |