自定义注解字典回显
业务:表中大量字段为字典值,列表查询需要关联多次字典表。为简化改过程,便有了该帖子。
1.创建注解
@Target({ ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = DictValidator.class)
@JacksonAnnotationsInside
@JsonSerialize(using = DictJsonSerializer.class)
public @interface Dict {
/**
* 字典的类型
*/
String value();
String message() default "值不在合法字典范围内";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
/**
* 是否转json时,拼接name属性;默认自动拼接
* @return
*/
boolean returnDictName() default true;
/**
* 是否转json时,拼接name属性 的 属性名
* @return
*/
String returnDictNameField() default "";
}
2.校验是否有该字典
import com.baomidou.mybatisplus.annotation.IEnum;
import com.iot.business.equipConfig.domain.TEospDictData;
import com.iot.business.equipConfig.service.ITEospDictTypeService;
import com.iot.common.annotation.DataSource;
import com.iot.common.enums.DataSourceType;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.List;
public class DictValidator implements ConstraintValidator<Dict, Object> {
String dictGroupValue;
@Autowired
private ITEospDictTypeService dictTypeService;
@Override
public void initialize(Dict constraintAnnotation) {
dictGroupValue = constraintAnnotation.value();
}
@Override
@DataSource(DataSourceType.SJZL)
public boolean isValid(Object dictObject, ConstraintValidatorContext context) {
if (dictObject == null) {
return true;
}
// 根据字典类型查询是否有该类型的字典,该方法实现里面引入了redis缓存。
List<TEospDictData> itemList = dictTypeService.selectDictDataByType(dictGroupValue);
///查询数据库里面存储的值
String dictObjectValue = null;
if (dictObject instanceof IEnum) {
dictObjectValue = ((IEnum) dictObject).getValue() + StringUtils.EMPTY;
} else {
dictObjectValue = dictObject + StringUtils.EMPTY;
}
for (TEospDictData item : itemList){
if(dictObjectValue.equals(item.getDictCode())){
return true;
}
}
return false;
}
}
3.序列化返回值
import com.baomidou.mybatisplus.annotation.IEnum;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fasterxml.jackson.databind.ser.std.NullSerializer;
import com.iot.business.annotation.validate.Dict;
import com.iot.business.equipConfig.domain.TEospDictData;
import com.iot.business.equipConfig.service.ITEospDictDataService;
import com.iot.common.utils.spring.SpringUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
public class DictJsonSerializer extends JsonSerializer<Object> implements ContextualSerializer {
private static String SUFFIX = "Str";
private boolean serialize;
/**
* 字典组code
*/
private String dictGroupCode;
private String addFiledName;
/**
* 字段名称
*/
private String originFieldName;
public DictJsonSerializer() {}
public DictJsonSerializer(String originFieldName, boolean serialize, String addFiledName, String dictGroupCode) {
this.originFieldName = originFieldName;
this.serialize = serialize;
this.addFiledName = addFiledName;
this.dictGroupCode = dictGroupCode;
}
@Override
public void serialize(Object dictValueObject, JsonGenerator gen, SerializerProvider serializers) throws IOException {
// 字段本身的输出
serializers.findValueSerializer(dictValueObject.getClass()).serialize(dictValueObject, gen, serializers);
if (!this.serialize) {
return;
}
String dictNameFiled = this.originFieldName + SUFFIX;
if (StringUtils.isNotEmpty(this.addFiledName)) {
dictNameFiled = this.addFiledName;
}
// 字典项name的输出
gen.writeFieldName(dictNameFiled);
String itemName = StringUtils.EMPTY;
TEospDictData item = null;
ITEospDictDataService dictDataService = SpringUtils.getBean(ITEospDictDataService.class);
if (dictDataService != null) {
String dictValue = null;
if (dictValueObject instanceof IEnum) {
// 枚举类的,如果没有数据字典项,则返回枚举的message;如果有数据字典项使用字典项名称
dictValue = ((IEnum) dictValueObject).getValue() + StringUtils.EMPTY;
} else {
dictValue = dictValueObject + StringUtils.EMPTY;
}
// 根据字典类型和字典值查询字典回显名称,先从redis缓存中获取。
itemName = dictDataService.selectDictItem(this.dictGroupCode, dictValue);
}
gen.writeString(itemName);
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
if (beanProperty != null) {
String filedName = beanProperty.getName();
Dict dict = beanProperty.getAnnotation(Dict.class);
if (dict != null) {
// 如果能得到注解,就将注解的 value 传入 SensitiveInfoSerialize
return new DictJsonSerializer(filedName, dict.returnDictName(), dict.returnDictNameField(), dict.value());
}
return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
}
return NullSerializer.instance;
}
}
4.使用该注解
@Data
@TableName("t_student")
@EqualsAndHashCode(callSuper = false)
@ApiModel(description = "xx***学生")
public class TStudent implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@ApiModelProperty(value = "主键")
@TableId(value = "id", type = IdType.ASSIGN_ID)
private String id;
/**
* 性别 字典
*/
@ApiModelProperty(value = "性别 字典")
@Dict(value = "sex", returnDictNameField = "sexName")
private String sex;
5.结果
[
{
"id" : "1128978721",
"sex" : "1",
"sexName" : "女"
},{}
]