mirror of
https://gitee.com/orangeform/orange-admin.git
synced 2026-01-17 18:46:36 +08:00
commit
This commit is contained in:
233
orange-demo-service/common/common-redis/common-redis.iml
Normal file
233
orange-demo-service/common/common-redis/common-redis.iml
Normal file
@@ -0,0 +1,233 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="Spring" name="Spring">
|
||||
<configuration />
|
||||
</facet>
|
||||
<facet type="web" name="Web">
|
||||
<configuration>
|
||||
<webroots />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
|
||||
<output url="file://$MODULE_DIR$/target/classes" />
|
||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="common-core" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:2.2.5.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.2.5.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.10.2" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.10.2" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:2.2.5.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:9.0.31" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:9.0.31" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:9.0.31" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-validation:2.2.5.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: jakarta.validation:jakarta.validation-api:2.0.2" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.hibernate.validator:hibernate-validator:6.0.18.Final" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.4.1.Final" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.fasterxml:classmate:1.5.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework:spring-webmvc:5.2.4.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework:spring-expression:5.2.4.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.google.guava:guava:28.2-android" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.google.guava:failureaccess:1.0.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.google.code.findbugs:jsr305:3.0.2" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.checkerframework:checker-compat-qual:2.5.5" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.google.errorprone:error_prone_annotations:2.3.4" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.google.j2objc:j2objc-annotations:1.3" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.9" level="project" />
|
||||
<orderEntry type="library" name="Maven: commons-codec:commons-codec:1.13" level="project" />
|
||||
<orderEntry type="library" name="Maven: commons-io:commons-io:2.6" level="project" />
|
||||
<orderEntry type="library" name="Maven: commons-fileupload:commons-fileupload:1.3.3" level="project" />
|
||||
<orderEntry type="library" name="Maven: joda-time:joda-time:2.10.5" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-collections4:4.4" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-csv:1.8" level="project" />
|
||||
<orderEntry type="library" name="Maven: cn.hutool:hutool-all:5.1.5" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.jsonwebtoken:jjwt:0.9.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.alibaba:fastjson:1.2.70" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.github.ben-manes.caffeine:caffeine:2.8.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.checkerframework:checker-qual:3.1.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: cn.jimmyshi:bean-query:1.1.5" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.hamcrest:hamcrest-all:1.3" level="project" />
|
||||
<orderEntry type="library" name="Maven: commons-beanutils:commons-beanutils:1.9.3" level="project" />
|
||||
<orderEntry type="library" name="Maven: commons-collections:commons-collections:3.2.2" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.30" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml:3.17" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.poi:poi:3.17" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.poi:poi-ooxml-schemas:3.17" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.xmlbeans:xmlbeans:2.6.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: stax:stax-api:1.0.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.github.virtuald:curvesapi:1.04" level="project" />
|
||||
<orderEntry type="library" scope="RUNTIME" name="Maven: mysql:mysql-connector-java:8.0.19" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.alibaba:druid-spring-boot-starter:1.1.22" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.alibaba:druid:1.1.22" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:2.2.5.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: tk.mybatis:mapper-spring-boot-starter:2.1.5" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:2.2.5.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.zaxxer:HikariCP:3.4.2" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework:spring-jdbc:5.2.4.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework:spring-tx:5.2.4.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.mybatis:mybatis:3.4.6" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.mybatis:mybatis-spring:1.3.2" level="project" />
|
||||
<orderEntry type="library" name="Maven: tk.mybatis:mapper-core:1.1.5" level="project" />
|
||||
<orderEntry type="library" name="Maven: javax.persistence:persistence-api:1.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: tk.mybatis:mapper-base:1.1.5" level="project" />
|
||||
<orderEntry type="library" name="Maven: tk.mybatis:mapper-weekend:1.1.5" level="project" />
|
||||
<orderEntry type="library" name="Maven: tk.mybatis:mapper-spring:1.1.5" level="project" />
|
||||
<orderEntry type="library" name="Maven: tk.mybatis:mapper-extra:1.1.5" level="project" />
|
||||
<orderEntry type="library" name="Maven: tk.mybatis:mapper-spring-boot-autoconfigure:2.1.5" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper-spring-boot-starter:1.2.13" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-starter:2.1.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.mybatis.spring.boot:mybatis-spring-boot-autoconfigure:2.1.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper-spring-boot-autoconfigure:1.2.13" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.github.pagehelper:pagehelper:5.1.11" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.github.jsqlparser:jsqlparser:2.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: redis.clients:jedis:3.2.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.30" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.commons:commons-pool2:2.7.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.redisson:redisson:3.12.3" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.netty:netty-common:4.1.45.Final" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.netty:netty-codec:4.1.45.Final" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.netty:netty-buffer:4.1.45.Final" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.netty:netty-transport:4.1.45.Final" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.netty:netty-resolver:4.1.45.Final" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.netty:netty-resolver-dns:4.1.45.Final" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.netty:netty-codec-dns:4.1.45.Final" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.netty:netty-handler:4.1.45.Final" level="project" />
|
||||
<orderEntry type="library" name="Maven: javax.cache:cache-api:1.1.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.projectreactor:reactor-core:3.3.3.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.reactivestreams:reactive-streams:1.0.3" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.reactivex.rxjava2:rxjava:2.2.18" level="project" />
|
||||
<orderEntry type="library" name="Maven: de.ruedigermoeller:fst:2.57" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.javassist:javassist:3.21.0-GA" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.objenesis:objenesis:2.6" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.yaml:snakeyaml:1.25" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.10.2" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.10.2" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.10.2" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.10.2" level="project" />
|
||||
<orderEntry type="library" name="Maven: net.bytebuddy:byte-buddy:1.10.8" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.jodd:jodd-bean:5.0.13" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.jodd:jodd-core:5.0.13" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-freemarker:2.2.5.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.2.5.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:2.2.5.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: jakarta.annotation:jakarta.annotation-api:1.3.5" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.freemarker:freemarker:2.3.29" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework:spring-context-support:5.2.4.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework:spring-beans:5.2.4.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework:spring-context:5.2.4.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: javax.servlet:javax.servlet-api:4.0.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-log4j2:2.2.5.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-slf4j-impl:2.12.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.12.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-core:2.12.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-jul:2.12.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.30" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-aop:2.2.5.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework:spring-aop:5.2.4.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.aspectj:aspectjweaver:1.9.5" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-cache:2.2.5.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-configuration-processor:2.2.5.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-actuator:2.2.5.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-actuator-autoconfigure:2.2.5.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-actuator:2.2.5.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.10.2" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.micrometer:micrometer-core:1.3.5" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.hdrhistogram:HdrHistogram:2.1.11" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.latencyutils:LatencyUtils:2.0.3" level="project" />
|
||||
<orderEntry type="library" name="Maven: de.codecentric:spring-boot-admin-starter-client:2.2.3" level="project" />
|
||||
<orderEntry type="library" name="Maven: de.codecentric:spring-boot-admin-client:2.2.3" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-config:2.2.1.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.alibaba.spring:spring-context-support:1.0.6" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.alibaba.nacos:nacos-client:1.2.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.alibaba.nacos:nacos-common:1.2.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.alibaba.nacos:nacos-api:1.2.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.prometheus:simpleclient:0.5.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-commons:2.2.2.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-crypto:5.2.2.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-context:2.2.2.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-openfeign:2.2.2.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter:2.2.2.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.security:spring-security-rsa:1.0.9.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.bouncycastle:bcpkix-jdk15on:1.59" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.bouncycastle:bcprov-jdk15on:1.59" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-openfeign-core:2.2.2.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.github.openfeign.form:feign-form-spring:3.8.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.github.openfeign.form:feign-form:3.8.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework:spring-web:5.2.4.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.github.openfeign:feign-core:10.7.4" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.github.openfeign:feign-slf4j:10.7.4" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.github.openfeign:feign-hystrix:10.7.4" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.netflix.archaius:archaius-core:0.7.6" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.github.openfeign:feign-httpclient:10.7.4" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.5.11" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.4.13" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-netflix-hystrix:2.2.2.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-netflix-hystrix:2.2.2.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-netflix-ribbon:2.2.2.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-netflix-archaius:2.2.2.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-netflix-archaius:2.2.2.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: commons-configuration:commons-configuration:1.8" level="project" />
|
||||
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.6" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.netflix.hystrix:hystrix-core:1.5.18" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.reactivex:rxjava:1.3.8" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.netflix.hystrix:hystrix-serialization:1.5.18" level="project" />
|
||||
<orderEntry type="library" scope="RUNTIME" name="Maven: com.fasterxml.jackson.module:jackson-module-afterburner:2.10.2" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.netflix.hystrix:hystrix-metrics-event-stream:1.5.18" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.netflix.hystrix:hystrix-javanica:1.5.18" level="project" />
|
||||
<orderEntry type="library" scope="RUNTIME" name="Maven: org.ow2.asm:asm:5.0.4" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.reactivex:rxjava-reactive-streams:1.2.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.mapstruct:mapstruct:1.3.1.Final" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.mapstruct:mapstruct-processor:1.3.1.Final" level="project" />
|
||||
<orderEntry type="library" scope="PROVIDED" name="Maven: org.projectlombok:lombok:1.18.12" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.curator:curator-recipes:4.3.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.curator:curator-framework:4.0.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.curator:curator-client:4.0.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.zookeeper:zookeeper:3.5.3-beta" level="project" />
|
||||
<orderEntry type="library" name="Maven: commons-cli:commons-cli:1.4" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.apache.kafka:kafka-clients:2.4.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.github.luben:zstd-jni:1.4.3-1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.lz4:lz4-java:1.6.0" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.xerial.snappy:snappy-java:1.1.7.3" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.scala-lang:scala-library:2.12.10" level="project" />
|
||||
<orderEntry type="library" name="Maven: com.lmax:disruptor:3.4.2" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:2.2.5.RELEASE" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:2.2.5.RELEASE" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:2.2.5.RELEASE" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.4.0" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:json-smart:2.3" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:accessors-smart:1.2" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: jakarta.xml.bind:jakarta.xml.bind-api:2.3.2" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: jakarta.activation:jakarta.activation-api:1.2.2" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter:5.5.2" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-api:5.5.2" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.opentest4j:opentest4j:1.2.0" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-commons:1.5.2" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-params:5.5.2" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-engine:5.5.2" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.junit.vintage:junit-vintage-engine:5.5.2" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.apiguardian:apiguardian-api:1.1.0" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-engine:1.5.2" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-junit-jupiter:3.1.0" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:3.13.2" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest:2.1" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:3.1.0" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy-agent:1.10.8" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.5.0" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework:spring-core:5.2.4.RELEASE" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:5.2.4.RELEASE" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:5.2.4.RELEASE" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="Maven: org.xmlunit:xmlunit-core:2.6.3" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
34
orange-demo-service/common/common-redis/pom.xml
Normal file
34
orange-demo-service/common/common-redis/pom.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?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>common</artifactId>
|
||||
<groupId>com.orange.demo</groupId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>common-redis</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<name>common-redis</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.orange.demo</groupId>
|
||||
<artifactId>common-core</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
<version>${jedis.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.redisson</groupId>
|
||||
<artifactId>redisson</artifactId>
|
||||
<version>${redisson.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,410 @@
|
||||
package com.orange.demo.common.redis.cache;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.orange.demo.common.core.cache.DictionaryCache;
|
||||
import com.orange.demo.common.core.exception.RedisCacheAccessException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.redisson.api.RMap;
|
||||
import org.redisson.api.RReadWriteLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 字典数据Redis缓存对象。
|
||||
*
|
||||
* @param <K> 字典表主键类型。
|
||||
* @param <V> 字典表对象类型。
|
||||
* @author Orange Team
|
||||
* @date 2020-08-08
|
||||
*/
|
||||
@Slf4j
|
||||
public class RedisDictionaryCache<K, V> implements DictionaryCache<K, V> {
|
||||
|
||||
/**
|
||||
* redisson客户端。
|
||||
*/
|
||||
protected RedissonClient redissonClient;
|
||||
/**
|
||||
* 数据存储对象。
|
||||
*/
|
||||
protected RMap<K, String> dataMap;
|
||||
/**
|
||||
* 字典值对象类型。
|
||||
*/
|
||||
protected Class<V> valueClazz;
|
||||
/**
|
||||
* 由于大部分场景是读取操作,所以使用读写锁提高并发的伸缩性。
|
||||
*/
|
||||
protected RReadWriteLock lock;
|
||||
/**
|
||||
* 超时时长。单位毫秒。
|
||||
*/
|
||||
protected static final long TIMEOUT = 2000L;
|
||||
/**
|
||||
* 获取字典主键数据的函数对象。
|
||||
*/
|
||||
protected Function<V, K> idGetter;
|
||||
|
||||
/**
|
||||
* 当前对象的构造器函数。
|
||||
*
|
||||
* @param redissonClient Redisson的客户端对象。
|
||||
* @param dictionaryName 字典表的名称。等同于redis hash对象的key。
|
||||
* @param valueClazz 值对象的Class对象。
|
||||
* @param idGetter 获取当前类主键字段值的函数对象。
|
||||
* @param <K> 字典主键类型。
|
||||
* @param <V> 字典对象类型
|
||||
* @return 实例化后的字典内存缓存对象。
|
||||
*/
|
||||
public static <K, V> RedisDictionaryCache<K, V> create(
|
||||
RedissonClient redissonClient,
|
||||
String dictionaryName,
|
||||
Class<V> valueClazz,
|
||||
Function<V, K> idGetter) {
|
||||
if (idGetter == null) {
|
||||
throw new IllegalArgumentException("IdGetter can't be NULL.");
|
||||
}
|
||||
return new RedisDictionaryCache<>(redissonClient, dictionaryName, valueClazz, idGetter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造函数。
|
||||
*
|
||||
* @param redissonClient Redisson的客户端对象。
|
||||
* @param dictionaryName 字典表的名称。等同于redis hash对象的key。确保全局唯一。
|
||||
* @param valueClazz 值对象的Class对象。
|
||||
* @param idGetter 获取当前类主键字段值的函数对象。
|
||||
*/
|
||||
public RedisDictionaryCache(
|
||||
RedissonClient redissonClient,
|
||||
String dictionaryName,
|
||||
Class<V> valueClazz,
|
||||
Function<V, K> idGetter) {
|
||||
this.redissonClient = redissonClient;
|
||||
this.dataMap = redissonClient.getMap(dictionaryName + "-DICT");
|
||||
this.lock = redissonClient.getReadWriteLock(dictionaryName + "-DICT-LOCK");
|
||||
this.valueClazz = valueClazz;
|
||||
this.idGetter = idGetter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按照数据插入的顺序返回全部字典对象的列表。
|
||||
*
|
||||
* @return 全部字段数据列表。
|
||||
*/
|
||||
@Override
|
||||
public List<V> getAll() {
|
||||
Collection<String> dataList;
|
||||
String exceptionMessage;
|
||||
try {
|
||||
if (lock.readLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
|
||||
try {
|
||||
dataList = dataMap.readAllValues();
|
||||
} finally {
|
||||
// 如果上面的操作时间超过redisson.lockWatchdogTimeout的时长,
|
||||
// redis会将与该锁关联的键删除,此后调用unlock的时候,就会抛出运行时异常。
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
} else {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exceptionMessage = String.format(
|
||||
"LOCK Operation of [RedisDictionaryCache::getAll] encountered EXCEPTION [%s] for DICT [%s].",
|
||||
e.getClass().getSimpleName(), valueClazz.getSimpleName());
|
||||
log.warn(exceptionMessage);
|
||||
throw new RedisCacheAccessException(exceptionMessage, e);
|
||||
}
|
||||
if (CollectionUtils.isEmpty(dataList)) {
|
||||
return new LinkedList<>();
|
||||
}
|
||||
return dataList.stream()
|
||||
.map(data -> JSON.parseObject(data, valueClazz))
|
||||
.collect(Collectors.toCollection(LinkedList::new));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存中与键列表对应的对象列表。
|
||||
*
|
||||
* @param keys 主键集合。
|
||||
* @return 对象列表。
|
||||
*/
|
||||
@Override
|
||||
public List<V> getInList(Set<K> keys) {
|
||||
if (CollectionUtils.isEmpty(keys)) {
|
||||
return new LinkedList<>();
|
||||
}
|
||||
Collection<String> dataList;
|
||||
String exceptionMessage;
|
||||
try {
|
||||
if (lock.readLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
|
||||
try {
|
||||
dataList = dataMap.getAll(keys).values();
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
} else {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exceptionMessage = String.format(
|
||||
"LOCK Operation of [RedisDictionaryCache::getInList] encountered EXCEPTION [%s] for DICT [%s].",
|
||||
e.getClass().getSimpleName(), valueClazz.getSimpleName());
|
||||
log.warn(exceptionMessage);
|
||||
throw new RedisCacheAccessException(exceptionMessage, e);
|
||||
}
|
||||
if (dataList == null) {
|
||||
return new LinkedList<>();
|
||||
}
|
||||
return dataList.stream()
|
||||
.map(data -> JSON.parseObject(data, valueClazz))
|
||||
.collect(Collectors.toCollection(LinkedList::new));
|
||||
}
|
||||
|
||||
/**
|
||||
* 从缓存中获取指定的数据。
|
||||
*
|
||||
* @param id 数据的key。
|
||||
* @return 获取到的数据,如果没有返回null。
|
||||
*/
|
||||
@Override
|
||||
public V get(K id) {
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
String data;
|
||||
String exceptionMessage;
|
||||
try {
|
||||
if (lock.readLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
|
||||
try {
|
||||
data = dataMap.get(id);
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
} else {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exceptionMessage = String.format(
|
||||
"LOCK Operation of [RedisDictionaryCache::get] encountered EXCEPTION [%s] for DICT [%s].",
|
||||
e.getClass().getSimpleName(), valueClazz.getSimpleName());
|
||||
log.warn(exceptionMessage);
|
||||
throw new RedisCacheAccessException(exceptionMessage, e);
|
||||
}
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
return JSON.parseObject(data, valueClazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存中数据条目的数量。
|
||||
*
|
||||
* @return 返回缓存的数据数量。
|
||||
*/
|
||||
@Override
|
||||
public int getCount() {
|
||||
return dataMap.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将参数List中的数据保存到缓存中,同时保证getAll返回的数据列表,与参数列表中数据项的顺序保持一致。
|
||||
*
|
||||
* @param dataList 待缓存的数据列表。
|
||||
*/
|
||||
@Override
|
||||
public void putAll(List<V> dataList) {
|
||||
if (CollectionUtils.isEmpty(dataList)) {
|
||||
return;
|
||||
}
|
||||
Map<K, String> map = dataList.stream()
|
||||
.collect(Collectors.toMap(idGetter, JSON::toJSONString));
|
||||
String exceptionMessage;
|
||||
try {
|
||||
if (lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
|
||||
try {
|
||||
dataMap.putAll(map, 1000);
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
} else {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exceptionMessage = String.format(
|
||||
"LOCK Operation of [RedisDictionaryCache::putAll] encountered EXCEPTION [%s] for DICT [%s].",
|
||||
e.getClass().getSimpleName(), valueClazz.getSimpleName());
|
||||
log.warn(exceptionMessage);
|
||||
throw new RedisCacheAccessException(exceptionMessage, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将数据存入缓存。
|
||||
*
|
||||
* @param id 通常为字典数据的主键。
|
||||
* @param data 字典数据对象。
|
||||
*/
|
||||
@Override
|
||||
public void put(K id, V data) {
|
||||
if (id == null || data == null) {
|
||||
return;
|
||||
}
|
||||
String exceptionMessage;
|
||||
try {
|
||||
if (lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
|
||||
try {
|
||||
dataMap.fastPut(id, JSON.toJSONString(data));
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
} else {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exceptionMessage = String.format(
|
||||
"LOCK Operation of [RedisDictionaryCache::put] encountered EXCEPTION [%s] for DICT [%s].",
|
||||
e.getClass().getSimpleName(), valueClazz.getSimpleName());
|
||||
log.warn(exceptionMessage);
|
||||
throw new RedisCacheAccessException(exceptionMessage, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新加载,先清空原有数据,在执行putAll的操作。
|
||||
*
|
||||
* @param dataList 待缓存的数据列表。
|
||||
* @param force true则强制刷新,如果false,当缓存中存在数据时不刷新。
|
||||
*/
|
||||
@Override
|
||||
public void reload(List<V> dataList, boolean force) {
|
||||
Map<K, String> map = null;
|
||||
if (CollectionUtils.isNotEmpty(dataList)) {
|
||||
map = dataList.stream().collect(Collectors.toMap(idGetter, JSON::toJSONString));
|
||||
}
|
||||
String exceptionMessage;
|
||||
try {
|
||||
if (lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
|
||||
try {
|
||||
// 如果不强制刷新,需要先判断缓存中是否存在数据。
|
||||
if (!force && this.getCount() > 0) {
|
||||
return;
|
||||
}
|
||||
dataMap.clear();
|
||||
if (map != null) {
|
||||
dataMap.putAll(map, 1000);
|
||||
}
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
} else {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exceptionMessage = String.format(
|
||||
"LOCK Operation of [RedisDictionaryCache::reload] encountered EXCEPTION [%s] for DICT [%s].",
|
||||
e.getClass().getSimpleName(), valueClazz.getSimpleName());
|
||||
log.warn(exceptionMessage);
|
||||
throw new RedisCacheAccessException(exceptionMessage, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除缓存中指定的键。
|
||||
*
|
||||
* @param id 待删除数据的主键。
|
||||
* @return 返回被删除的对象,如果主键不存在,返回null。
|
||||
*/
|
||||
@Override
|
||||
public V invalidate(K id) {
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
String data;
|
||||
String exceptionMessage;
|
||||
try {
|
||||
if (lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
|
||||
try {
|
||||
data = dataMap.remove(id);
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
} else {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exceptionMessage = String.format(
|
||||
"LOCK Operation of [RedisDictionaryCache::invalidate] encountered EXCEPTION [%s] for DICT [%s].",
|
||||
e.getClass().getSimpleName(), valueClazz.getSimpleName());
|
||||
log.warn(exceptionMessage);
|
||||
throw new RedisCacheAccessException(exceptionMessage, e);
|
||||
}
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
return JSON.parseObject(data, valueClazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除缓存中,参数列表中包含的键。
|
||||
*
|
||||
* @param keys 待删除数据的主键集合。
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void invalidateSet(Set<K> keys) {
|
||||
if (CollectionUtils.isEmpty(keys)) {
|
||||
return;
|
||||
}
|
||||
Object[] keyArray = keys.toArray(new Object[]{});
|
||||
String exceptionMessage;
|
||||
try {
|
||||
if (lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
|
||||
try {
|
||||
dataMap.fastRemove((K[]) keyArray);
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
} else {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exceptionMessage = String.format(
|
||||
"LOCK Operation of [RedisDictionaryCache::invalidateSet] encountered EXCEPTION [%s] for DICT [%s].",
|
||||
e.getClass().getSimpleName(), valueClazz.getSimpleName());
|
||||
log.warn(exceptionMessage);
|
||||
throw new RedisCacheAccessException(exceptionMessage, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空缓存。
|
||||
*/
|
||||
@Override
|
||||
public void invalidateAll() {
|
||||
String exceptionMessage;
|
||||
try {
|
||||
if (lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
|
||||
try {
|
||||
dataMap.clear();
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
} else {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exceptionMessage = String.format(
|
||||
"LOCK Operation of [RedisDictionaryCache::invalidateAll] encountered EXCEPTION [%s] for DICT [%s].",
|
||||
e.getClass().getSimpleName(), valueClazz.getSimpleName());
|
||||
log.warn(exceptionMessage);
|
||||
throw new RedisCacheAccessException(exceptionMessage, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,352 @@
|
||||
package com.orange.demo.common.redis.cache;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.orange.demo.common.core.exception.RedisCacheAccessException;
|
||||
import com.google.common.collect.LinkedListMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.redisson.api.RListMultimap;
|
||||
import org.redisson.api.RedissonClient;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 树形字典数据Redis缓存对象。
|
||||
*
|
||||
* @param <K> 字典表主键类型。
|
||||
* @param <V> 字典表对象类型。
|
||||
* @author Orange Team
|
||||
* @date 2020-08-08
|
||||
*/
|
||||
@Slf4j
|
||||
public class RedisTreeDictionaryCache<K, V> extends RedisDictionaryCache<K, V> {
|
||||
|
||||
/**
|
||||
* 树形数据存储对象。
|
||||
*/
|
||||
private RListMultimap<K, String> allTreeMap;
|
||||
/**
|
||||
* 获取字典父主键数据的函数对象。
|
||||
*/
|
||||
protected Function<V, K> parentIdGetter;
|
||||
|
||||
/**
|
||||
* 当前对象的构造器函数。
|
||||
*
|
||||
* @param redissonClient Redisson的客户端对象。
|
||||
* @param dictionaryName 字典表的名称。等同于redis hash对象的key。
|
||||
* @param valueClazz 值对象的Class对象。
|
||||
* @param idGetter 获取当前类主键字段值的函数对象。
|
||||
* @param parentIdGetter 获取当前类父主键字段值的函数对象。
|
||||
* @param <K> 字典主键类型。
|
||||
* @param <V> 字典对象类型
|
||||
* @return 实例化后的树形字典内存缓存对象。
|
||||
*/
|
||||
public static <K, V> RedisTreeDictionaryCache<K, V> create(
|
||||
RedissonClient redissonClient,
|
||||
String dictionaryName,
|
||||
Class<V> valueClazz,
|
||||
Function<V, K> idGetter,
|
||||
Function<V, K> parentIdGetter) {
|
||||
if (idGetter == null) {
|
||||
throw new IllegalArgumentException("IdGetter can't be NULL.");
|
||||
}
|
||||
if (parentIdGetter == null) {
|
||||
throw new IllegalArgumentException("ParentIdGetter can't be NULL.");
|
||||
}
|
||||
return new RedisTreeDictionaryCache<>(
|
||||
redissonClient, dictionaryName, valueClazz, idGetter, parentIdGetter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造函数。
|
||||
*
|
||||
* @param redissonClient Redisson的客户端对象。
|
||||
* @param dictionaryName 字典表的名称。等同于redis hash对象的key。
|
||||
* @param valueClazz 值对象的Class对象。
|
||||
* @param idGetter 获取当前类主键字段值的函数对象。
|
||||
* @param parentIdGetter 获取当前类父主键字段值的函数对象。
|
||||
*/
|
||||
public RedisTreeDictionaryCache(
|
||||
RedissonClient redissonClient,
|
||||
String dictionaryName,
|
||||
Class<V> valueClazz,
|
||||
Function<V, K> idGetter,
|
||||
Function<V, K> parentIdGetter) {
|
||||
super(redissonClient, dictionaryName, valueClazz, idGetter);
|
||||
this.allTreeMap = redissonClient.getListMultimap(dictionaryName + "-TREE-DICT");
|
||||
this.parentIdGetter = parentIdGetter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取该父主键的子数据列表。
|
||||
*
|
||||
* @param parentId 父主键Id。如果parentId为null,则返回所有一级节点数据。
|
||||
* @return 子数据列表。
|
||||
*/
|
||||
public List<V> getListByParentId(K parentId) {
|
||||
List<String> dataList;
|
||||
String exceptionMessage;
|
||||
try {
|
||||
if (lock.readLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
|
||||
try {
|
||||
dataList = allTreeMap.get(parentId);
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
} else {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exceptionMessage = String.format(
|
||||
"LOCK Operation of [RedisTreeDictionaryCache::getListByParentId] encountered EXCEPTION [%s] for DICT [%s].",
|
||||
e.getClass().getSimpleName(), valueClazz.getSimpleName());
|
||||
log.warn(exceptionMessage);
|
||||
throw new RedisCacheAccessException(exceptionMessage, e);
|
||||
}
|
||||
if (CollectionUtils.isEmpty(dataList)) {
|
||||
return new LinkedList<>();
|
||||
}
|
||||
List<V> resultList = new LinkedList<>();
|
||||
dataList.forEach(data -> resultList.add(JSON.parseObject(data, valueClazz)));
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将参数List中的数据保存到缓存中,同时保证getAll返回的数据列表,与参数列表中数据项的顺序保持一致。
|
||||
*
|
||||
* @param dataList 待缓存的数据列表。
|
||||
*/
|
||||
@Override
|
||||
public void putAll(List<V> dataList) {
|
||||
if (CollectionUtils.isEmpty(dataList)) {
|
||||
return;
|
||||
}
|
||||
// 锁外执行数据结构组装,降低锁的粒度,提高并发性。
|
||||
Map<K, String> map = dataList.stream()
|
||||
.collect(Collectors.toMap(idGetter, JSON::toJSONString));
|
||||
Multimap<K, String> treeMap = LinkedListMultimap.create();
|
||||
for (V data : dataList) {
|
||||
treeMap.put(parentIdGetter.apply(data), JSON.toJSONString(data));
|
||||
}
|
||||
Set<Map.Entry<K, Collection<String>>> entries = treeMap.asMap().entrySet();
|
||||
String exceptionMessage;
|
||||
try {
|
||||
if (this.lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
|
||||
try {
|
||||
dataMap.putAll(map, 1000);
|
||||
for (Map.Entry<K, Collection<String>> entry : entries) {
|
||||
allTreeMap.removeAll(entry.getKey());
|
||||
allTreeMap.putAll(entry.getKey(), entry.getValue());
|
||||
}
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
} else {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exceptionMessage = String.format(
|
||||
"LOCK Operation of [RedisTreeDictionaryCache::putAll] encountered EXCEPTION [%s] for DICT [%s].",
|
||||
e.getClass().getSimpleName(), valueClazz.getSimpleName());
|
||||
log.warn(exceptionMessage);
|
||||
throw new RedisCacheAccessException(exceptionMessage, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将数据存入缓存。
|
||||
*
|
||||
* @param id 通常为字典数据的主键。
|
||||
* @param data 字典数据对象。
|
||||
*/
|
||||
@Override
|
||||
public void put(K id, V data) {
|
||||
if (id == null || data == null) {
|
||||
return;
|
||||
}
|
||||
String stringData = JSON.toJSONString(data);
|
||||
K parentId = parentIdGetter.apply(data);
|
||||
String exceptionMessage;
|
||||
try {
|
||||
if (this.lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
|
||||
try {
|
||||
String oldData = dataMap.put(id, stringData);
|
||||
if (oldData != null) {
|
||||
allTreeMap.remove(parentId, oldData);
|
||||
}
|
||||
allTreeMap.put(parentId, stringData);
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
} else {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exceptionMessage = String.format(
|
||||
"LOCK Operation of [RedisTreeDictionaryCache::put] encountered EXCEPTION [%s] for DICT [%s].",
|
||||
e.getClass().getSimpleName(), valueClazz.getSimpleName());
|
||||
log.warn(exceptionMessage);
|
||||
throw new RedisCacheAccessException(exceptionMessage, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 行为等同于接口中的描述。这里之所以重写,是因为不确定redisson的读写锁,
|
||||
* 是否为可重入锁。
|
||||
*
|
||||
* @param dataList 待缓存的数据列表。
|
||||
* @param force true则强制刷新,如果false,当缓存中存在数据时不刷新。
|
||||
*/
|
||||
@Override
|
||||
public void reload(List<V> dataList, boolean force) {
|
||||
// 锁外执行数据结构组装,降低锁的粒度,提高并发性。
|
||||
Map<K, String> map = null;
|
||||
Set<Map.Entry<K, Collection<String>>> entries = null;
|
||||
if (CollectionUtils.isNotEmpty(dataList)) {
|
||||
map = dataList.stream().collect(Collectors.toMap(idGetter, JSON::toJSONString));
|
||||
Multimap<K, String> treeMap = LinkedListMultimap.create();
|
||||
for (V data : dataList) {
|
||||
treeMap.put(parentIdGetter.apply(data), JSON.toJSONString(data));
|
||||
}
|
||||
entries = treeMap.asMap().entrySet();
|
||||
}
|
||||
String exceptionMessage;
|
||||
try {
|
||||
if (lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
|
||||
try {
|
||||
// 如果不强制刷新,需要先判断缓存中是否存在数据。
|
||||
if (!force && this.getCount() > 0) {
|
||||
return;
|
||||
}
|
||||
dataMap.clear();
|
||||
allTreeMap.clear();
|
||||
if (map != null) {
|
||||
dataMap.putAll(map, 1000);
|
||||
for (Map.Entry<K, Collection<String>> entry : entries) {
|
||||
allTreeMap.removeAll(entry.getKey());
|
||||
allTreeMap.putAll(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
} else {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exceptionMessage = String.format(
|
||||
"LOCK Operation of [RedisDictionaryCache::reload] encountered EXCEPTION [%s] for DICT [%s].",
|
||||
e.getClass().getSimpleName(), valueClazz.getSimpleName());
|
||||
log.warn(exceptionMessage);
|
||||
throw new RedisCacheAccessException(exceptionMessage, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除缓存中指定的键。
|
||||
*
|
||||
* @param id 待删除数据的主键。
|
||||
* @return 返回被删除的对象,如果主键不存在,返回null。
|
||||
*/
|
||||
@Override
|
||||
public V invalidate(K id) {
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
V data = null;
|
||||
String exceptionMessage;
|
||||
try {
|
||||
if (this.lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
|
||||
try {
|
||||
String stringData = dataMap.remove(id);
|
||||
if (stringData != null) {
|
||||
data = JSON.parseObject(stringData, valueClazz);
|
||||
K parentId = parentIdGetter.apply(data);
|
||||
allTreeMap.remove(parentId, stringData);
|
||||
}
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
} else {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exceptionMessage = String.format(
|
||||
"LOCK Operation of [RedisTreeDictionaryCache::invalidate] encountered EXCEPTION [%s] for DICT [%s].",
|
||||
e.getClass().getSimpleName(), valueClazz.getSimpleName());
|
||||
log.warn(exceptionMessage);
|
||||
throw new RedisCacheAccessException(exceptionMessage, e);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除缓存中,参数列表中包含的键。
|
||||
*
|
||||
* @param keys 待删除数据的主键集合。
|
||||
*/
|
||||
@Override
|
||||
public void invalidateSet(Set<K> keys) {
|
||||
if (CollectionUtils.isEmpty(keys)) {
|
||||
return;
|
||||
}
|
||||
String exceptionMessage;
|
||||
try {
|
||||
if (lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
|
||||
try {
|
||||
keys.forEach(id -> {
|
||||
if (id != null) {
|
||||
String stringData = dataMap.remove(id);
|
||||
if (stringData != null) {
|
||||
K parentId = parentIdGetter.apply(JSON.parseObject(stringData, valueClazz));
|
||||
allTreeMap.remove(parentId, stringData);
|
||||
}
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
} else {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exceptionMessage = String.format(
|
||||
"LOCK Operation of [RedisTreeDictionaryCache::invalidateSet] encountered EXCEPTION [%s] for DICT [%s].",
|
||||
e.getClass().getSimpleName(), valueClazz.getSimpleName());
|
||||
log.warn(exceptionMessage);
|
||||
throw new RedisCacheAccessException(exceptionMessage, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空缓存。
|
||||
*/
|
||||
@Override
|
||||
public void invalidateAll() {
|
||||
String exceptionMessage;
|
||||
try {
|
||||
if (lock.writeLock().tryLock(TIMEOUT, TimeUnit.MILLISECONDS)) {
|
||||
try {
|
||||
dataMap.clear();
|
||||
allTreeMap.clear();
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
} else {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
exceptionMessage = String.format(
|
||||
"LOCK Operation of [RedisTreeDictionaryCache::invalidateAll] encountered EXCEPTION [%s] for DICT [%s].",
|
||||
e.getClass().getSimpleName(), valueClazz.getSimpleName());
|
||||
log.warn(exceptionMessage);
|
||||
throw new RedisCacheAccessException(exceptionMessage, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.orange.demo.common.redis.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
import redis.clients.jedis.JedisPoolConfig;
|
||||
|
||||
/**
|
||||
* Redis配置类。
|
||||
*
|
||||
* @author Orange Team
|
||||
* @date 2020-08-08
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(name = "redis.jedis.enabled", havingValue = "true")
|
||||
public class JedisConfig {
|
||||
|
||||
@Value("${redis.jedis.port}")
|
||||
private Integer port;
|
||||
|
||||
@Value("${redis.jedis.host}")
|
||||
private String redisHost;
|
||||
|
||||
@Value("${redis.jedis.timeout}")
|
||||
private int timeout;
|
||||
|
||||
@Value("${redis.jedis.pool.maxTotal}")
|
||||
private Integer maxTotal;
|
||||
|
||||
@Value("${redis.jedis.pool.maxIdle}")
|
||||
private Integer maxIdle;
|
||||
|
||||
@Value("${redis.jedis.pool.minIdle}")
|
||||
private Integer minIdle;
|
||||
|
||||
@Value("${redis.jedis.pool.maxWait}")
|
||||
private Integer maxWait;
|
||||
|
||||
@Bean
|
||||
public JedisPool getJedisPool() {
|
||||
//Jedis配置信息
|
||||
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
|
||||
jedisPoolConfig.setMaxTotal(maxTotal);
|
||||
jedisPoolConfig.setMaxIdle(maxIdle);
|
||||
jedisPoolConfig.setMinIdle(minIdle);
|
||||
jedisPoolConfig.setMaxWaitMillis(maxWait);
|
||||
jedisPoolConfig.setEvictorShutdownTimeoutMillis(2000);
|
||||
return new JedisPool(jedisPoolConfig, redisHost, port);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.orange.demo.common.redis.config;
|
||||
|
||||
import org.redisson.Redisson;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.redisson.config.Config;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Redisson配置类。和Jedis一样都是Redis客户端,但是Redisson提供了更多的数据结构抽象。
|
||||
* 这里我们只是使用了Redisson的分布式锁,以及map等数据结构作为字典缓存使用。更多用法请参考其文档。
|
||||
*
|
||||
* @author Orange Team
|
||||
* @date 2020-08-08
|
||||
*/
|
||||
@Configuration
|
||||
@ConditionalOnProperty(name = "redis.redisson.enabled", havingValue = "true")
|
||||
public class RedissonConfig {
|
||||
|
||||
@Value("${redis.redisson.lockWatchdogTimeout}")
|
||||
private Integer lockWatchdogTimeout;
|
||||
|
||||
@Value("${redis.redisson.address}")
|
||||
private String address;
|
||||
|
||||
@Value("${redis.redisson.timeout}")
|
||||
private Integer timeout;
|
||||
|
||||
@Value("${redis.redisson.pool.poolSize}")
|
||||
private Integer poolSize;
|
||||
|
||||
@Value("${redis.redisson.pool.minIdle}")
|
||||
private Integer minIdle;
|
||||
|
||||
@Bean
|
||||
public RedissonClient redissonClient() {
|
||||
Config config = new Config();
|
||||
// 这里config还支持其他redis集群模式,可根据实际需求更换。
|
||||
// 比如useClusterServers()/useMasterSlaveServers()等。
|
||||
config.setLockWatchdogTimeout(lockWatchdogTimeout)
|
||||
.useSingleServer()
|
||||
.setAddress("redis://" + address)
|
||||
.setConnectionPoolSize(poolSize)
|
||||
.setConnectionMinimumIdleSize(minIdle)
|
||||
.setConnectTimeout(timeout);
|
||||
return Redisson.create(config);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
com.orange.demo.common.redis.config.JedisConfig,\
|
||||
com.orange.demo.common.redis.config.RedissonConfig
|
||||
Reference in New Issue
Block a user