Skip to content

Commit

Permalink
update 优化注释
Browse files Browse the repository at this point in the history
  • Loading branch information
Robot committed Nov 24, 2023
1 parent 2f3af1f commit 96cb033
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 38 deletions.
63 changes: 32 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,21 @@
/**
* 性别枚举示例
*/
public enum Sex implements Dict<Integer> {
public enum SexEnum implements Dict<Integer> {
MALE(1, ""),
FEMALE(2, ""),
UNKNOWN(3, "未知");

Sex(Integer code, String text) {
SexEnum(Integer code, String text) {
// 一个init方法搞定,该方法来自Dict接口
init(code, text);
}
}
```
你没看错,原先的属性定义、get方法、工具方法全部省略,仅仅只需要在构造方法中调用`init()`方法即可。接着就能通过`getCode()``getText()`方法获取枚举的编码值和文本。
```java
Integer code = Sex.MALE.getCode(); // 1
String text = Sex.MALE.getText(); // "男"
Integer code = SexEnum.MALE.getCode(); // 1
String text = SexEnum.MALE.getText(); // "男"
```

> Dict的含义即为字典,拥有编码和文本两个固定属性,而在业务开发中定义的枚举大都是就是字典,所以抽象成接口,省略枚举类中重复代码。
Expand All @@ -47,22 +47,22 @@ String text = Sex.MALE.getText(); // "男"
Dict接口除了优化枚举申明,还提供了大量实用的api:
```java
// 1、通过code获取text
String text = Dict.getTextByCode(Sex.class, 1); // "男"
String text = Dict.getTextByCode(SexEnum.class, 1); // "男"
// 2、通过text获取code
Integer code = Dict.getCodeByText(Sex.class, ""); // 1
Integer code = Dict.getCodeByText(SexEnum.class, ""); // 1
// 3、通过code获取枚举
Sex sex = Dict.getByCode(Sex.class, 1); // Sex.MALE
SexEnum sex = Dict.getByCode(SexEnum.class, 1); // SexEnum.MALE
```
转换成字典项集合,常用于给前端下拉框展示使用
```java
// 4、获取枚举的所有元素
List<DictBean> all = Dict.getAll(Sex.class); // [{code:1,text:"男"},{code:2,text:"女"},{code:3,text:"未知"}]
List<DictBean> all = Dict.getAll(SexEnum.class); // [{code:1,text:"男"},{code:2,text:"女"},{code:3,text:"未知"}]
// 5、获取枚举的指定元素
List<DictBean> items = Dict.getItems(Sex.MALE, Sex.FEMALE); // [{code:1,text:"男"},{code:2,text:"女"}]
List<DictBean> items = Dict.getItems(SexEnum.MALE, SexEnum.FEMALE); // [{code:1,text:"男"},{code:2,text:"女"}]
// 6、排除指定元素,获取其他元素
List<DictBean> items = Dict.getItemsExclude(Sex.UNKNOWN); // [{code:1,text:"男"},{code:2,text:"女"}]
List<DictBean> items = Dict.getItemsExclude(SexEnum.UNKNOWN); // [{code:1,text:"男"},{code:2,text:"女"}]
```
上例中的DictBean是Dict的一个实现类,用于存储和展示真实的枚举数据,DictBean申明如下
上例中的DictBean是Dict的一个实现类,用于存储真正的枚举数据,DictBean定义如下
```java
public class DictBean implements Dict<Object> {
/**
Expand All @@ -74,38 +74,39 @@ public class DictBean implements Dict<Object> {
*/
private final String text;
/**
* 是否过期
* 一般来说,过期的字典项不能用于新增,而查询时需要作文本翻译
* 是否废弃
*/
private final boolean isDeprecated;
private final transient boolean isDeprecated;

}
```
其中`isDeprecated`属性的作用是如果我们在枚举项上使用`@Deprecated`注解时,这个属性的值就会为true
其中`isDeprecated`属性的作用是如果我们在枚举项上使用`@Deprecated`注解时,这个属性的值就会为true。

示例:
```java
public enum Sex implements Dict<Integer> {
public enum SexEnum implements Dict<Integer> {
MALE(1, ""),
FEMALE(2, ""),
@Deprecated
UNKNOWN(3, "未知");
...
}
// UNKOWN对应的数据体中isDeprecated为true
List<DictBean> all = Dict.getAll(Sex.class); // [{code:1,text:"男"},{code:2,text:"女"},{code:3,text:"未知",isDeprecated:true}]

// 使用getAll()的重载方法,第二个入参表示是否排除废弃枚举项
List<DictBean> all = Dict.getAll(SexEnum.class, true); // [{code:1,text:"男"},{code:2,text:"女"}]
```

有了这些工具方法,枚举类中再也不用写重复的方法代码了。

### 3.Spring开发支持
#### 3.1 Post请求DTO/VO中使用枚举属性
在以往的接口开发中,是不是当DTO中有枚举含义的字段时,都是用int类型来处理,然后代码中写逻辑时需要这样:
在以往的接口开发中,当DTO中有枚举含义的字段时,常常是用Integer类型来定义,然后代码中写逻辑时需要这样:
```java
// 实际上这段代码还会告警,提示应使用equals
if(student.getSex() == SexEnum.MALE.getCode()){
...
}
```
又比如当遇到switch-case时,代码也会相当不优雅
又比如当遇到switch-case时,代码也稍显麻烦
```java
// 写法1,直接用魔法值
switch(studentDTO.getSex()){
Expand All @@ -128,26 +129,26 @@ public class StudentDTO {

}

// 代码中:
// 写switch-case很顺畅
switch(studentDTO.getSex()){
case MALE: System.out.print("");break;
case FEMAL: System.out.print("");break;
}
```
> 这里DTO、VO都支持使用枚举属性,因为对枚举的json序列化和反序列化做了支持
> 这里DTO、VO都支持直接用枚举类型的属性,因为组件对Dict枚举的json序列化和反序列化做了支持
>
> 源码参考:DictJacksonConfiguration
#### 3.2 支持Get请求方法出入参使用枚举
接口参数除了Json序列化方式,也有可能是Get请求参数方式,也做了支持
接口参数除了Json序列化方式,也有可能是Get请求参数方式,组件同样也做了支持
```java
@GetMapping("/listStudentBySex")
public List<Student> listStudent(Sex sex){
public List<Student> listStudent(SexEnum sex){
...
}
```
> 这里无论是入参还是出参都可以使用枚举,因为对枚举对Spring的converter做了支持
>
> 源码参考:DictSpringConvertConfiguration
> 源码参考:DictSpringConvertConfintion
#### 3.3 Feign调用支持枚举参数传输
Feign调用时,方法参数会先在调用方序列化成url请求参数进行传输,到达被调用方后再反序列化成方法入参,这里也对枚举做了支持
Expand All @@ -159,14 +160,14 @@ Feign调用时,方法参数会先在调用方序列化成url请求参数进行
public interface StudentFeignClient {

@GetMapping("/listStudentBySex")
List<Student> listStudent(Sex sex); //直接使用枚举入参
List<Student> listStudent(SexEnum sex); //直接使用枚举入参
}

// 调用方:
@Resource
private StudentFeignClient studentFeignClient;
...
List<Student> studentList = studentFeignClient.listStudent(Sex.MALE);
List<Student> studentList = studentFeignClient.listStudent(SexEnum.MALE);
```
> 源码参考:DictSpringConvertConfiguration
Expand All @@ -185,10 +186,10 @@ public class Student{
```java
Wrapper<Student> wrapper = new LambdaQueryWrapper<>(); // QueryWrapper同理
// 之前
wrapper.eq(Student::sex, Sex.MALE.getCode());
wrapper.eq(Student::sex, SexEnum.MALE.getCode());
// 之后
wrapper.eq(Student::sex, Sex.MALE);
// 注意:这里的代码简化不是必须要求Student类中的sex属性类型是枚举,定义为Integer同样有效
wrapper.eq(Student::sex, SexEnum.MALE);
// 注意:这里的代码简化不要求Student类中的sex属性类型必须是枚举,Integer类型同样有效
```
> 源码参考:DictMybatisConfiguration
## 使用方式
Expand Down
15 changes: 13 additions & 2 deletions easy-enum/src/main/java/com/robot/dict/Dict.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,9 +95,20 @@ static <T, K extends Dict<T>> K getByCode(Class<K> clazz, T code) {
* @return List
*/
static <T> List<DictBean> getAll(Class<? extends Dict<T>> clazz) {
return DictPool.getAll(clazz);
return getAll(clazz, false);
}

/**
* 获取所有字典枚举项(常用下拉框数据请求)
* 可以选择是否包含废弃枚举项
*
* @param clazz 字典枚举类
* @param isExcludeDeprecated 是否排除废弃选项,枚举项上使用@Deprecated注解标识废弃
* @return List
*/
static <T> List<DictBean> getAll(Class<? extends Dict<T>> clazz, boolean isExcludeDeprecated) {
return DictPool.getAll(clazz, true);
}

/**
* 获取给定的字典枚举项(常用下拉框数据请求)
Expand All @@ -121,7 +132,7 @@ static <E extends Dict<?>> List<DictBean> getItems(E... enums) {
@SuppressWarnings("unchecked")
static <E extends Dict<?>> List<DictBean> getItemsExclude(E... excludeEnums) {
Class<? extends Dict<?>> enmuClass = (Class<? extends Dict<?>>) excludeEnums.getClass().getComponentType();
List<DictBean> allDict = DictPool.getAll(enmuClass);
List<DictBean> allDict = DictPool.getAll(enmuClass, false);
List<?> excluceCodeList = Stream.of(excludeEnums).map(Dict::getCode).collect(Collectors.toList());
return allDict.stream()
.filter(dictBean -> !excluceCodeList.contains(dictBean.getCode()))
Expand Down
5 changes: 3 additions & 2 deletions easy-enum/src/main/java/com/robot/dict/DictBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ public class DictBean implements Dict<Object> {
private final String text;
/**
* 是否过期
* 一般来说,过期的字典项不能用于新增,而查询时需要作文本翻译
* <p>在枚举选项上使用@Deprecated注解标志过期
* <p>该属性不会被序列化
*/
private final boolean isDeprecated;
private final transient boolean isDeprecated;

public DictBean(Object code, String text) {
this.code = code;
Expand Down
13 changes: 10 additions & 3 deletions easy-enum/src/main/java/com/robot/dict/DictPool.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
* 字典池,所有Dict的实现类都会在这里注册
Expand Down Expand Up @@ -45,13 +46,19 @@ static DictBean getDict(Dict<?> dict) {
return DICT_MAP.get(dict);
}


/**
* 根据class获取字典集合
* 根据class获取字典集合,可以选择是否排除过期选项
* 枚举上使用@Deprecated注解标识过期选项
*/
static List<DictBean> getAll(Class<? extends Dict<?>> clazz) {
static List<DictBean> getAll(Class<? extends Dict<?>> clazz, boolean isExcludeDeprecated) {
// 触发实例化枚举对象,避免并发问题导致未实例化拿不到数据,这比任何加锁方式都要简单快速
clazz.getEnumConstants();
return DICT_CLASS_ITEMS_MAP.get(clazz);
List<DictBean> dictBeans = DICT_CLASS_ITEMS_MAP.get(clazz);
if (isExcludeDeprecated) {
return dictBeans.stream().filter(dictBean -> !dictBean.getIsDeprecated()).collect(Collectors.toList());
}
return dictBeans;
}

private DictPool() {
Expand Down
7 changes: 7 additions & 0 deletions easy-enum/src/test/java/com/robot/dict/DictTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ void getAll() {
assertEquals(3, all.size());
}

@Test
void getAllExcludeDeprecated() {
List<DictBean> all = Dict.getAll(Sex.class,true);
System.out.println(JSON.toJSONString(all));
assertEquals(2, all.size());
}

@Test
void getItems() {
List<DictBean> items = Dict.getItems(Sex.MALE, Sex.FEMALE);
Expand Down

0 comments on commit 96cb033

Please sign in to comment.