|
@@ -0,0 +1,106 @@
|
|
|
+package com.backendsys.modules.common.aspect;
|
|
|
+
|
|
|
+import cn.hutool.core.convert.Convert;
|
|
|
+import com.backendsys.modules.common.utils.Result;
|
|
|
+import com.backendsys.modules.common.utils.ResultEnum;
|
|
|
+import org.aspectj.lang.ProceedingJoinPoint;
|
|
|
+import org.aspectj.lang.annotation.Around;
|
|
|
+import org.aspectj.lang.annotation.Aspect;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.context.ApplicationContext;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+
|
|
|
+import java.io.Serializable;
|
|
|
+import java.lang.reflect.Field;
|
|
|
+import java.lang.reflect.Method;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 仅判断非空,可以使用此切面方法
|
|
|
+ *
|
|
|
+ * 多判断,不适合此方法,比如:
|
|
|
+ * - 非空
|
|
|
+ * - 非本人
|
|
|
+ * - 非超级管理员
|
|
|
+ */
|
|
|
+
|
|
|
+@Aspect
|
|
|
+@Component
|
|
|
+public class QueryNullCheckAspectV2 {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ApplicationContext applicationContext;
|
|
|
+
|
|
|
+ private static Map<String, Object> queryResult;
|
|
|
+ private static Object queryResultV2;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 自定注解:@QueryNullCheck
|
|
|
+ * 使用方法:通过ID查询记录是否存在 (适用于 详情/改/删)
|
|
|
+ * @QueryNullCheck(serviceClass = B2cGoodUnitService.class, serviceMethod = "queryGoodUnitDetail", argField = "good_unit_id", message = "商品单位不存在")
|
|
|
+ * public Result deleteGoodUnit(@Validated(B2cGoodUnitDTO.Delete.class) @RequestBody B2cGoodUnitDTO b2cGoodUnitDTO) {
|
|
|
+ *
|
|
|
+ * 注意:入参必须是实体类 (除 GET 外,POST/PUT/DELETE 需要加 @RequestBody)
|
|
|
+ */
|
|
|
+ @SuppressWarnings({"rawtypes", "unchecked"})
|
|
|
+ @Around("@annotation(queryNullCheckV2)")
|
|
|
+ public Object handleQueryNullCheck(ProceedingJoinPoint joinPoint, QueryNullCheckV2 queryNullCheckV2) throws Throwable {
|
|
|
+ Object[] args = joinPoint.getArgs();
|
|
|
+
|
|
|
+ Class argDao = queryNullCheckV2.dao();
|
|
|
+ String argField = queryNullCheckV2.field();
|
|
|
+ String argMessage = queryNullCheckV2.message();
|
|
|
+
|
|
|
+
|
|
|
+ // 拿不到实例化后的
|
|
|
+
|
|
|
+// Class<?> implClass = argDao.getClass();
|
|
|
+// Method[] methods = implClass.getDeclaredMethods();
|
|
|
+// for (Method method : methods) {
|
|
|
+// System.out.println(method.getName());
|
|
|
+// }
|
|
|
+
|
|
|
+
|
|
|
+ // 获取参数值
|
|
|
+ Serializable argValue = null;
|
|
|
+ for (Object arg : args) {
|
|
|
+ Field field = arg.getClass().getDeclaredField(argField);
|
|
|
+ field.setAccessible(true);
|
|
|
+ argValue = Convert.toLong(field.get(arg));
|
|
|
+ if (argValue != null) { break; }
|
|
|
+ }
|
|
|
+ System.out.println("argValue = " + argValue);
|
|
|
+ System.out.println("argValue.getClass() = " + argValue.getClass());
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 参数为空 (例如 user_id = null) 时,校验在实体类那里进行,此处不再进行校验
|
|
|
+ */
|
|
|
+ if (argValue != null) {
|
|
|
+
|
|
|
+ // 拿不到 selectById 方法
|
|
|
+ // 在MyBatis-Plus中,BaseMapper<T>接口中定义的方法(如selectById)是通过MyBatis-Plus框架在运行时动态生成的代理实现的。这些方法并不是直接在DAO接口的实现类中定义的,而是在代理对象中动态创建的。因此,使用Java反射API直接在DAO接口的实现类中查找这些方法是找不到的。
|
|
|
+
|
|
|
+
|
|
|
+//// queryResultV2 = argDao.getClass().getMethod("selectById", argValue.getClass()).invoke(argDao, argValue);
|
|
|
+// queryResultV2 = argDao.getClass().getMethod("selectById", Serializable.class).invoke(argDao, argValue);
|
|
|
+// System.out.println("queryResultV2 = " + queryResultV2);
|
|
|
+
|
|
|
+
|
|
|
+// // [反向代理] 执行记录非空查询的 service 方法
|
|
|
+// queryResult = (Map<String, Object>) service.getClass().getMethod(serviceMethod, argValue.getClass()).invoke(service, argValue);
|
|
|
+// if (queryResult == null) {
|
|
|
+// return Result.error(ResultEnum.DATABASE_OPERATION_FAILED.getCode(), message);
|
|
|
+// }
|
|
|
+ }
|
|
|
+
|
|
|
+ return joinPoint.proceed();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获得该次查询的结果:
|
|
|
+ * QueryNullCheckAspect.getQueryResult()
|
|
|
+ */
|
|
|
+ public static Map<String, Object> getQueryResult() {
|
|
|
+ return queryResult;
|
|
|
+ }
|
|
|
+}
|