From 9b342f76c403a819ceb28fb3f931da466afbe60d Mon Sep 17 00:00:00 2001 From: ZhangXushuo <3508242435.com> Date: Tue, 17 Oct 2023 19:07:26 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.gitignore | 8 ++ .idea/compiler.xml | 13 ++++ .idea/encodings.xml | 8 ++ .idea/misc.xml | 16 ++++ .idea/vcs.xml | 6 ++ pom.xml | 28 +++++++ src/main/java/com/bawei/cache/BaseCache.java | 61 +++++++++++++++ .../com/bawei/cache/annotation/CacheRole.java | 22 ++++++ .../com/bawei/cache/aspect/CacheRuleAsp.java | 70 ++++++++++++++++++ .../com/bawei/cache/db/BaseDatabaseCache.java | 25 +++++++ ...ot.autoconfigure.AutoConfiguration.imports | 1 + target/bawei-common-cache-3.6.0.jar | Bin 0 -> 6169 bytes ...ot.autoconfigure.AutoConfiguration.imports | 1 + .../classes/com/bawei/cache/BaseCache$1.class | Bin 0 -> 809 bytes .../classes/com/bawei/cache/BaseCache.class | Bin 0 -> 1456 bytes .../bawei/cache/annotation/CacheRole.class | Bin 0 -> 454 bytes .../com/bawei/cache/aspect/CacheRuleAsp.class | Bin 0 -> 2259 bytes .../bawei/cache/db/BaseDatabaseCache.class | Bin 0 -> 426 bytes target/maven-archiver/pom.properties | 5 ++ .../compile/default-compile/createdFiles.lst | 5 ++ .../compile/default-compile/inputFiles.lst | 4 + 21 files changed, 273 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/compiler.xml create mode 100644 .idea/encodings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/vcs.xml create mode 100644 pom.xml create mode 100644 src/main/java/com/bawei/cache/BaseCache.java create mode 100644 src/main/java/com/bawei/cache/annotation/CacheRole.java create mode 100644 src/main/java/com/bawei/cache/aspect/CacheRuleAsp.java create mode 100644 src/main/java/com/bawei/cache/db/BaseDatabaseCache.java create mode 100644 src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 target/bawei-common-cache-3.6.0.jar create mode 100644 target/classes/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 target/classes/com/bawei/cache/BaseCache$1.class create mode 100644 target/classes/com/bawei/cache/BaseCache.class create mode 100644 target/classes/com/bawei/cache/annotation/CacheRole.class create mode 100644 target/classes/com/bawei/cache/aspect/CacheRuleAsp.class create mode 100644 target/classes/com/bawei/cache/db/BaseDatabaseCache.class create mode 100644 target/maven-archiver/pom.properties create mode 100644 target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst create mode 100644 target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..a27726c --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..78bf31c --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..354accf --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,16 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..beb1148 --- /dev/null +++ b/pom.xml @@ -0,0 +1,28 @@ + + + + bawei-common + com.bawei + 3.6.0 + + 4.0.0 + + bawei-common-cache + + + 8 + 8 + UTF-8 + + + + + + + com.bawei + bawei-common-redis + + + diff --git a/src/main/java/com/bawei/cache/BaseCache.java b/src/main/java/com/bawei/cache/BaseCache.java new file mode 100644 index 0000000..0e1b2ca --- /dev/null +++ b/src/main/java/com/bawei/cache/BaseCache.java @@ -0,0 +1,61 @@ +package com.bawei.cache; + +import com.bawei.common.core.utils.thread.ThreadPool; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * @author DongZl + * @description: 缓存基准 + * @Date 2022-10-18 下午 02:57 + */ +public interface BaseCache { + + public static final long time = 2; + + @Autowired + public ThreadPool threadPool = null; + + /** + * 获取Redis的key 用来 对缓存进行操作 + * @param key 数据Id + * @return + */ + public String getKey(K key); + + /** + * 增/改 + * @param key 键 + * @param val 值 + * @return + */ + public boolean put(K key, V val); + + /** + * 删 + * @param key 键 + * @return + */ + public boolean remove(K key); + + /** + * 延迟删 + * @param key 键 + */ + public default void delayRemove(K key){ + ThreadPool.getThreadPool().delayExecute(time, new Runnable() { + @Override + public void run () { + remove(key); + } + }); + } + + + /** + * 查 + * @param key 键 + * @return val 值 + */ + public V get(K key); + +} diff --git a/src/main/java/com/bawei/cache/annotation/CacheRole.java b/src/main/java/com/bawei/cache/annotation/CacheRole.java new file mode 100644 index 0000000..3dd7044 --- /dev/null +++ b/src/main/java/com/bawei/cache/annotation/CacheRole.java @@ -0,0 +1,22 @@ +package com.bawei.cache.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author DongZl + * @description: 缓存权限 + * @Date 2022-10-19 上午 08:34 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD, ElementType.TYPE }) +public @interface CacheRole { + + /** + * 允许操作缓存的微服务 + * @return + */ + public String serverName() ; +} diff --git a/src/main/java/com/bawei/cache/aspect/CacheRuleAsp.java b/src/main/java/com/bawei/cache/aspect/CacheRuleAsp.java new file mode 100644 index 0000000..5601ab2 --- /dev/null +++ b/src/main/java/com/bawei/cache/aspect/CacheRuleAsp.java @@ -0,0 +1,70 @@ +package com.bawei.cache.aspect; + +import com.bawei.cache.annotation.CacheRole; +import com.bawei.common.core.exception.ServiceException; +import com.bawei.common.core.utils.StringUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; + +/** + * @author DongZl + * @description: 缓存操作权限切面 + * @Date 2022-10-19 上午 08:36 + */ +@Aspect +@Component +public class CacheRuleAsp { + + /** + * 当前服务的名称 + */ + @Value("${spring.application.name}") + private String applicationName; + + + /** + * 定义AOP签名 (切入所有使用鉴权注解的方法) + */ + public static final String POINTCUT_SIGN = "@annotation(com.bawei.cache.annotation.CacheRole)"; + + /** + * 声明AOP切点 + */ + @Pointcut(POINTCUT_SIGN) + public void pointcut() + { + } + + /** + * 环绕切入 + * + * @param joinPoint 切面对象 + * @return 底层方法执行后的返回值 + * @throws Throwable 底层方法抛出的异常 + */ + @Around("pointcut()") + public Object around(ProceedingJoinPoint joinPoint) throws Throwable{ + // 注解鉴权 + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + // 获取注解的方法 + Method method = signature.getMethod(); + // 获取方法上面的注解 + CacheRole cacheRole = method.getAnnotation(CacheRole.class); + if (cacheRole != null){ + // 判断当前微服务是否要操作权限 + if (!cacheRole.serverName().equals(applicationName)){ + throw new ServiceException(StringUtils.format("当前服务[{}],无权限操作服务[{}]的缓存", + applicationName, + cacheRole.serverName())); + } + } + return joinPoint.proceed(); + } +} diff --git a/src/main/java/com/bawei/cache/db/BaseDatabaseCache.java b/src/main/java/com/bawei/cache/db/BaseDatabaseCache.java new file mode 100644 index 0000000..9667126 --- /dev/null +++ b/src/main/java/com/bawei/cache/db/BaseDatabaseCache.java @@ -0,0 +1,25 @@ +package com.bawei.cache.db; + +import com.bawei.cache.BaseCache; + +/** + * @author DongZl + * @description: 数据库缓存基类 + * @Date 2022-10-18 下午 03:05 + */ +public interface BaseDatabaseCache extends BaseCache { + + /** + * 通过ID获取数据库内数据 + * @param key 数据ID + * @return + */ + public V getData(K key); + + /** + * 基于Key进行刷新 + * @param key + * @return + */ + public boolean refreshData(K key); +} diff --git a/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..6d75df5 --- /dev/null +++ b/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.bawei.cache.aspect.CacheRuleAsp diff --git a/target/bawei-common-cache-3.6.0.jar b/target/bawei-common-cache-3.6.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..0b8a26869b1d32c8fc8486e06cbb1a5a7a9610aa GIT binary patch literal 6169 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 literal 0 HcmV?d00001 diff --git a/target/classes/com/bawei/cache/BaseCache.class b/target/classes/com/bawei/cache/BaseCache.class new file mode 100644 index 0000000000000000000000000000000000000000..4e1bb2e016f6dd9cb6f32dc6dcfefb14395f41ed GIT binary patch literal 1456 zcmah}?M@Rx6g|Vz7D^T5yCQyp(1Nfas7PxS8%=~p4Kz*k-*h{ah3zicodx??#zc)K zK7bEpyt9;bYm4lUoqJ~PJ$LSzJM-)J_n!dP@jQuDJV;a}ePw`g(C6COjaG#i3}Z8KacI<_adEi2seX)Y-bT)}Ja9LHkNONP_XtNc`$ zI#~_Jrok1uFHOtS&ph>V7?5K~@A|ePub7@$wZxWfJCaM2axiR^9Jj7}$F6DD_g&r) zr;dB1R|U5{eV-fBahp011N1FlI;W;9YD62a3%Mhj40D;%AwS`|#qGNOwt6TGnaf6| z_M~E`i2gmZZgc6oRMSMJywlxFJN6~Rd>7IP=XshB#HyIem0XtWxGNgY3DJ*r2@f2C zwB$KZ6Bcjo{?ENahf;KE#5PzmZSlr$RE1mSBq76a$uYQ9;jXE0YqD1!n55}c^n|!^ zAoLg96Gdf_2-=a-Y`C))hVgdN=J7f4%*BlPv*HVinM{%(sF3!q(fM3{I4vO=`hqyp zk<7ednYJklM3Tu8RX)G7*}36Lm$^cx8};v==ff!7$}aZH4Gl5iT=Lp(*+4NMdJP4cfJK^8Fb4Qv$J55(RtEPh4& z3lg7bTEi{+Cj*xyO0$OBgvZZ9a0hn@Q7~pOOSJde*5<;s`7n8gHj~9dh!@d^`&c5Z nHZx75`eN)e`c!%rq*s-KYSvm6E<-2WgB9AC+8m>YIQaemaB^yr literal 0 HcmV?d00001 diff --git a/target/classes/com/bawei/cache/annotation/CacheRole.class b/target/classes/com/bawei/cache/annotation/CacheRole.class new file mode 100644 index 0000000000000000000000000000000000000000..dae3f810f721daf2fe5f6250ad2605352c8a5552 GIT binary patch literal 454 zcmaixzfQw25XL{3wt)hrKoI3kv+wua`Oe=zpI-p3(DtzJ;lRV8KqI3xr*t3_5@?@aJWXXTeJxGwk6o%v ze9g?*&eMqQm1d@SE2DP`tftEX6*vm!#;Jr}RHi1HZj7-`I%Q2J&{;_*mjOQ@N35}i zlh<;o=bX3u4?411MGF>q!Sf(|?DqtY*Goc~#^jhhT_5jhO1ONum=QzuelL6&-U(F0 z*AXW@i)`XgSKO*eguy7X;LR4gdfE literal 0 HcmV?d00001 diff --git a/target/classes/com/bawei/cache/aspect/CacheRuleAsp.class b/target/classes/com/bawei/cache/aspect/CacheRuleAsp.class new file mode 100644 index 0000000000000000000000000000000000000000..27b1e7e84ecd76919ba08107f7def976c0994941 GIT binary patch literal 2259 zcma)8ZBHCk6n-x3GB6CK#nzTm>kH8CLc7x{t@2_it}TMFAiJOxYrQ*MVCe45I5P`2 zO+V=u8%a#~pf)wpA7G-1X+?|nlOOySCPL#U|3TxKnSGh`nh#?8DHlrRFBn->Ah>>PQ@mdr1BPru`T#|6P5u*~`kTHgF88Y7V z+$JPUGPH8b%IO++b<;@kykKaXSmkS6&2eK{O}n;kEDtiY&lC(-&x<+T(X%-*Vi>0D z`#21J6Q;eaI+ka;WD~}^XYTNpw97JK@eng&3j=u+I2JVO@yc< z48pm^&@w$WmdYe&GuP5%qbZsvO~Y}y;rb|z=wxUZ(hc3cz)&BH&oM-j<|3iCPUwb6 z74lhOXE-tT@-j7^o8z|b&5Mf>cSWZZx+gR8E0pAP(T;r1UaYLgC``f+lkmeNDqD#ll$jH8%8A=%!B}J% zh}DLfwoOflMN)g5qWF;p#~356<+NF_HE~(@C>;pG1_z$-F2a9;`h`NE zfmlyo1IHD%Fx?xLP?KifG7Vw4g9?tKL&CIzw=lyH^X^YoB~{B-R#`zB86xz5WFv_b z%wkT#+jvL80klb&S8xRj3}-?BW^XS^-{k@uLTuJKui6u)oqwg1VIOu7az0 z&(q+Vg7-lRcZT@<+wEgGQh}=0hvBKpR%XRE*Ml41Rio=3CC{KN3%4vW!|__srLL+2svpg$k13R&*Z zA)$jcx{>080?$!N%&_`)9p(f?6`|Jg2tTABHLhUkD{t zLJuvKDOS-au6iw7vVxArP@P*53(wQ1Orein9sN-qgU*{~%`_gQ|3eO*MmrAs8%KPz zcKRApA3_H`kI{-sBcn0eb06$`-{cv3Hu#H&ah%?jzyQzUIhrww*+J1f=U#tKYfn1% zh8$VZu|(_zf*@j@G<2bx=y*tfK%y@*u+Y1OI);a+pFFjN2t(?0Tl5|p9wIsrX^;Gd z^X-u>NYqk(K;u0$-9h)ykmuW)quWsC>%GH=QGFh((gNg6Zs^T12KFQ8S-fe4cKNun-Oe~KaQ%RY`ClEO=5 z7^iR=5hTcSAJ}7LB&ZV3NH|OApdE&n%16`}C~=NJ&eLWcQSwBR>FpI7`+~8O%KB&W{0WFCpkY?KPj<1HB&!1F*zeu-zl*;)fvRH0lEk196O+cxPtRbi;`2_ zGIM|q6$7aNIV}mMQV--?Mg|phqf(N