From 02e2b15ad073c11432d193e574acb943aec4fd0a Mon Sep 17 00:00:00 2001
From: YunaiV <>
Date: Wed, 3 Apr 2019 19:17:04 +0800
Subject: [PATCH] =?UTF-8?q?=E5=90=8E=E7=AB=AF=EF=BC=9A=E5=A2=9E=E5=8A=A0?=
 =?UTF-8?q?=20InEnum=20=E8=87=AA=E5=AE=9A=E4=B9=89=20Validator=20=EF=BC=8C?=
 =?UTF-8?q?=E7=94=A8=E4=BA=8E=E6=A0=A1=E9=AA=8C=E4=BC=A0=E9=80=92=E7=9A=84?=
 =?UTF-8?q?=E5=AD=97=E6=AE=B5=EF=BC=8C=E5=9C=A8=E6=9E=9A=E4=B8=BE=E8=8C=83?=
 =?UTF-8?q?=E5=9B=B4=E5=86=85=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../iocoder/mall/admin/api/AdminService.java  |  7 +++-
 .../mall/admin/dataobject/AdminDO.java        |  9 -----
 .../mall/admin/service/AdminServiceImpl.java  | 20 +++-------
 .../framework/constant/CommonStatusEnum.java  | 15 ++++++-
 .../framework/core/IntArrayValuable.java      | 13 +++++++
 .../common/framework/validator/InEnum.java    | 27 +++++++++++++
 .../framework/validator/InEnumValidator.java  | 39 +++++++++++++++++++
 7 files changed, 103 insertions(+), 27 deletions(-)
 create mode 100644 common/common-framework/src/main/java/cn/iocoder/common/framework/core/IntArrayValuable.java
 create mode 100644 common/common-framework/src/main/java/cn/iocoder/common/framework/validator/InEnum.java
 create mode 100644 common/common-framework/src/main/java/cn/iocoder/common/framework/validator/InEnumValidator.java

diff --git a/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/AdminService.java b/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/AdminService.java
index 76903ffb..462016d0 100644
--- a/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/AdminService.java
+++ b/admin/admin-service-api/src/main/java/cn/iocoder/mall/admin/api/AdminService.java
@@ -1,5 +1,7 @@
 package cn.iocoder.mall.admin.api;
 
+import cn.iocoder.common.framework.constant.CommonStatusEnum;
+import cn.iocoder.common.framework.validator.InEnum;
 import cn.iocoder.common.framework.vo.CommonResult;
 import cn.iocoder.mall.admin.api.bo.AdminBO;
 import cn.iocoder.mall.admin.api.bo.AdminPageBO;
@@ -20,10 +22,11 @@ public interface AdminService {
 
     CommonResult<Boolean> updateAdmin(Integer adminId, AdminUpdateDTO adminUpdateDTO);
 
-    CommonResult<Boolean> updateAdminStatus(Integer adminId, Integer updateAdminId, Integer status);
+    CommonResult<Boolean> updateAdminStatus(Integer adminId, Integer updateAdminId,
+                                            @InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") Integer status);
 
     CommonResult<Boolean> deleteAdmin(Integer adminId, Integer updateAdminId);
 
     CommonResult<Boolean> assignRole(Integer adminId, Integer updateAdminId, Set<Integer> roleIds);
 
-}
\ No newline at end of file
+}
diff --git a/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/AdminDO.java b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/AdminDO.java
index adfb1242..8cfc4140 100644
--- a/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/AdminDO.java
+++ b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/AdminDO.java
@@ -7,15 +7,6 @@ import cn.iocoder.common.framework.dataobject.DeletableDO;
  */
 public class AdminDO extends DeletableDO {
 
-    /**
-     * 账号状态 - 开启
-     */
-    public static final Integer STATUS_ENABLE = 1;
-    /**
-     * 账号状态 - 禁用
-     */
-    public static final Integer STATUS_DISABLE = 2;
-
     /**
      * 管理员编号
      */
diff --git a/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/service/AdminServiceImpl.java b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/service/AdminServiceImpl.java
index 7dca1ef2..c71f21cc 100644
--- a/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/service/AdminServiceImpl.java
+++ b/admin/admin-service-impl/src/main/java/cn/iocoder/mall/admin/service/AdminServiceImpl.java
@@ -1,7 +1,7 @@
 package cn.iocoder.mall.admin.service;
 
+import cn.iocoder.common.framework.constant.CommonStatusEnum;
 import cn.iocoder.common.framework.constant.DeletedStatusEnum;
-import cn.iocoder.common.framework.constant.SysErrorCodeEnum;
 import cn.iocoder.common.framework.util.ServiceExceptionUtil;
 import cn.iocoder.common.framework.vo.CommonResult;
 import cn.iocoder.mall.admin.api.AdminService;
@@ -53,7 +53,7 @@ public class AdminServiceImpl implements AdminService {
             return ServiceExceptionUtil.error(AdminErrorCodeEnum.ADMIN_PASSWORD_ERROR.getCode());
         }
         // 账号被禁用
-        if (AdminDO.STATUS_DISABLE.equals(admin.getStatus())) {
+        if (CommonStatusEnum.DISABLE.getValue().equals(admin.getStatus())) {
             return ServiceExceptionUtil.error(AdminErrorCodeEnum.ADMIN_IS_DISABLE.getCode());
         }
         // 校验成功,返回管理员。并且,去掉一些非关键字段,考虑安全性。
@@ -87,7 +87,7 @@ public class AdminServiceImpl implements AdminService {
         // 保存到数据库
         AdminDO admin = AdminConvert.INSTANCE.convert(adminAddDTO)
                 .setPassword(encodePassword(adminAddDTO.getPassword())) // 加密密码
-                .setStatus(AdminDO.STATUS_ENABLE);
+                .setStatus(CommonStatusEnum.ENABLE.getValue());
         admin.setCreateTime(new Date());
         admin.setDeleted(DeletedStatusEnum.DELETED_NO.getValue());
         adminMapper.insert(admin);
@@ -118,10 +118,6 @@ public class AdminServiceImpl implements AdminService {
     @Override
     @Transactional
     public CommonResult<Boolean> updateAdminStatus(Integer adminId, Integer updateAdminId, Integer status) {
-        // 校验参数
-        if (!isValidStatus(status)) {
-            return CommonResult.error(SysErrorCodeEnum.VALIDATION_REQUEST_PARAM_ERROR.getCode(), "变更状态必须是开启(1)或关闭(2)"); // TODO 有点搓
-        }
         // 校验账号存在
         AdminDO admin = adminMapper.selectById(updateAdminId);
         if (admin == null) {
@@ -138,7 +134,7 @@ public class AdminServiceImpl implements AdminService {
         AdminDO updateAdmin = new AdminDO().setId(updateAdminId).setStatus(status);
         adminMapper.update(updateAdmin);
         // 如果是关闭管理员,则标记 token 失效。否则,管理员还可以继续蹦跶
-        if (AdminDO.STATUS_DISABLE.equals(status)) {
+        if (CommonStatusEnum.DISABLE.getValue().equals(status)) {
             oAuth2Service.removeToken(updateAdminId);
         }
         // TODO 插入操作日志
@@ -155,7 +151,7 @@ public class AdminServiceImpl implements AdminService {
             return ServiceExceptionUtil.error(AdminErrorCodeEnum.ADMIN_USERNAME_NOT_REGISTERED.getCode());
         }
         // 只有禁用的账号才可以删除
-        if (AdminDO.STATUS_ENABLE.equals(admin.getStatus())) {
+        if (CommonStatusEnum.ENABLE.getValue().equals(admin.getStatus())) {
             return ServiceExceptionUtil.error(AdminErrorCodeEnum.ADMIN_DELETE_ONLY_DISABLE.getCode());
         }
         // 标记删除 AdminDO
@@ -204,8 +200,4 @@ public class AdminServiceImpl implements AdminService {
         return DigestUtils.md5DigestAsHex(password.getBytes());
     }
 
-    private boolean isValidStatus(Integer status) {
-        return AdminDO.STATUS_ENABLE.equals(status)
-                || AdminDO.STATUS_DISABLE.equals(status);
-    }
-}
\ No newline at end of file
+}
diff --git a/common/common-framework/src/main/java/cn/iocoder/common/framework/constant/CommonStatusEnum.java b/common/common-framework/src/main/java/cn/iocoder/common/framework/constant/CommonStatusEnum.java
index 9139cfdc..2dde2e18 100644
--- a/common/common-framework/src/main/java/cn/iocoder/common/framework/constant/CommonStatusEnum.java
+++ b/common/common-framework/src/main/java/cn/iocoder/common/framework/constant/CommonStatusEnum.java
@@ -1,13 +1,19 @@
 package cn.iocoder.common.framework.constant;
 
+import cn.iocoder.common.framework.core.IntArrayValuable;
+
+import java.util.Arrays;
+
 /**
  * 通用状态枚举
  */
-public enum CommonStatusEnum {
+public enum CommonStatusEnum implements IntArrayValuable {
 
     ENABLE(1, "开启"),
     DISABLE(2, "关闭");
 
+    public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CommonStatusEnum::getValue).toArray();
+
     /**
      * 状态值
      */
@@ -48,4 +54,9 @@ public enum CommonStatusEnum {
                 || DISABLE.value.equals(status);
     }
 
-}
\ No newline at end of file
+    @Override
+    public int[] array() {
+        return ARRAYS;
+    }
+
+}
diff --git a/common/common-framework/src/main/java/cn/iocoder/common/framework/core/IntArrayValuable.java b/common/common-framework/src/main/java/cn/iocoder/common/framework/core/IntArrayValuable.java
new file mode 100644
index 00000000..152225ce
--- /dev/null
+++ b/common/common-framework/src/main/java/cn/iocoder/common/framework/core/IntArrayValuable.java
@@ -0,0 +1,13 @@
+package cn.iocoder.common.framework.core;
+
+/**
+ * 可生成 Int 数组的接口
+ */
+public interface IntArrayValuable {
+
+    /**
+     * @return int 数组
+     */
+    int[] array();
+
+}
diff --git a/common/common-framework/src/main/java/cn/iocoder/common/framework/validator/InEnum.java b/common/common-framework/src/main/java/cn/iocoder/common/framework/validator/InEnum.java
new file mode 100644
index 00000000..f0533b0e
--- /dev/null
+++ b/common/common-framework/src/main/java/cn/iocoder/common/framework/validator/InEnum.java
@@ -0,0 +1,27 @@
+package cn.iocoder.common.framework.validator;
+
+import cn.iocoder.common.framework.core.IntArrayValuable;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.*;
+
+@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Constraint(
+        validatedBy = InEnumValidator.class
+)
+public @interface InEnum {
+
+    /**
+     * @return 实现 EnumValuable 接口的
+     */
+    Class<? extends IntArrayValuable> value();
+
+    String message() default "必须在指定范围 {value}";
+
+    Class<?>[] groups() default {};
+    Class<? extends Payload>[] payload() default {};
+
+}
diff --git a/common/common-framework/src/main/java/cn/iocoder/common/framework/validator/InEnumValidator.java b/common/common-framework/src/main/java/cn/iocoder/common/framework/validator/InEnumValidator.java
new file mode 100644
index 00000000..7ddd5bc5
--- /dev/null
+++ b/common/common-framework/src/main/java/cn/iocoder/common/framework/validator/InEnumValidator.java
@@ -0,0 +1,39 @@
+package cn.iocoder.common.framework.validator;
+
+import cn.iocoder.common.framework.core.IntArrayValuable;
+
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class InEnumValidator implements ConstraintValidator<InEnum, Integer> {
+
+    private List<Integer> values;
+
+    @Override
+    public void initialize(InEnum annotation) {
+        IntArrayValuable[] values = annotation.value().getEnumConstants();
+        if (values.length == 0) {
+            this.values = Collections.emptyList();
+        } else {
+            this.values = Arrays.stream(values[0].array()).boxed().collect(Collectors.toList());
+        }
+    }
+
+    @Override
+    public boolean isValid(Integer value, ConstraintValidatorContext context) {
+        // 校验通过
+        if (values.contains(value)) {
+            return true;
+        }
+        // 校验不通过,自定义提示语句(因为,注解上的 value 是枚举类,无法获得枚举类的实际值)
+        context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值
+        context.buildConstraintViolationWithTemplate(context.getDefaultConstraintMessageTemplate()
+                .replaceAll("\\{value}", values.toString())).addConstraintViolation(); // 重新添加错误提示语句
+        return false;
+    }
+
+}
-- 
2.17.1