基于feign传参MultipartFile问题解决
366
2022-07-25
目录两种解决方案字典注解定义字典序列化与返序列化器的实现字典序列化与反序列工具类字典转换服务类字典缓存服务
两种解决方案
前端查询字典数据然后前端转码后端查询字典值,然后再转码返回给前段。
本文及时针对方案2 进行的改进
目标:
在需要返回给前段的字段上添加指定的注解例如:@DictDesc 则根据该字段定义的值结合注解配置生成 xxxDesc字段并自动赋值为注解属性值所对应的字典描述;
具体使用的技术涉及到jackson序列化与反序列化,其他jsON工具包也类型的效果;
字典注解定义
/**
* 字典类型字段自动生成Desc描述字段
*/
@Inherited
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@JacksonAnnotationsInside
@JsonSerialize(using = DictDescSerializer.class)
@JsonDeserialize(using = DictDescDeserializer.class)
public @interface DictDesc {
/**
* 枚举类型的class
* 取值:getValue, getCode, getStatus, name
* 描述:getDesc
*
* @return 字典类型
*/
Class extends Enum extends DictEnum>>[] enumType() default {};
/**
* 字典类型分组
*
* @return 字典类型
*/
String[] dictType() default {};
/**
* 字典转换失败时默认值
*
* @return String 默认zlbNKGCFb值
*/
String defaultValue() default "";
/**
* 是否抛出异常,默认不抛出异常,返回默认值
*
* @return true 转换失败则抛出异常,false 异常返回默认值
*/
boolean throwException() default false;
}
该注解中定义了解析该注解需要序列化器与返序列化器:
@JsonSerialize(using = DictDescSerializer.class)
@JsonDeserialize(using = DictDescDeserializer.class)
字典序列化与返序列化器的实现
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.aimilin.common.dict.annotation.DictDesc;
import com.aimilin.common.dict.service.impl.DictDescSerializerUtils;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Objects;
/**
* 字典类型返序列化器
*
* @author liujunguang1
* @version V1.0
* @date 2022/5/20 21:08
*/
@Slf4j
@NoArgsConstructor
public class DictDescDeserializer extends JsonDeserializer
/**
* 生成序列化字段后缀
*/
private static final String LABEL_SUFFIX = "Desc";
/**
* 参数类型
*/
private Class> rawClass;
/**
* 默认转换器
*/
private ConversionService converter;
/**
* 设置方法
*/
private Method writeMethod;
/**
* 字典配置信息
*/
private DictDesc dict;
public DictDescDeserializer(DictDesc dict, BeanProperty property) {
this.dict = dict;
this.rawClass = property.getType().getRawClass();
this.converter = new DefaultConversionService();
Class> targetClass = property.getMember().getDeclaringClass();
String writeField = property.getName() + LABEL_SUFFIX;
PropertyDescriptor propertyDescriptor = BeanUtils.getPropertyDescriptor(targetClass, writeField);
this.writeMethod = Objects.isNull(propertyDescriptor) ? null : propertyDescriptor.getWriteMethod();
if (Objects.isNull(this.writeMethod)) {
log.info("类:{},字典属性:{},没有写入方法:{},不设置值!", targetClass.getName(), property.getName(), writeField);
}
}
@Override
public JsonDeserializer> createContextual(DeserializationContext ctxt, BeanProperty property) throws JsonMappingException {
DictDesc dict = property.getAnnotation(DictDesc.class);
if (dict != null) {
return new DictDescDeserializer(dict, property);
}
return this;
}
@Override
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
Object result = this.getValue(p.getText());
this.setDictDesc(result, p.getCurrentName(), p.getCurrentValue());
return result;
}
/**
* 将数据类型转换为目标类型
*
* @param value 字符串值
* @return 目标类型值
* @throws IOException
*/
public Object getValue(String value) throws IOException {
return converter.convert(value, this.rawClass);
}
/**
* 设置字典会限制
*
* @param result 字典value
* @param currentName 当前属性名称
* @param currentValue 当前对象
*/
private void setDictDesc(Object result, String currentName, Object currentValue) {
try {
if (this.writeMethod != null) {
writeMethod.invoke(currentValue, DictDescSerializerUtils.getDesc(this.dict, currentName, result));
}
} catch (Exception e) {
log.error("类:{},字典属性:{},回显异常:{}", currentValue.getClass(), currentName, e.getMessage(), e);
}
}
}
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.aimilin.common.dict.annotation.DictDesc;
import com.aimilin.common.dict.service.impl.DictDescSerializerUtils;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
/**
* 字典序列化器
*
* @author liujunguang1
* @version V1.0
* @date 2022/5/20 20:48
*/
@Slf4j
@NoArgsConstructor
public class DictDescSerializer extends JsonSerializer
/**
* 生成序列化字段后缀
*/
private static final String LABEL_SUFFIX = "Desc";
/**
* 字典配置信息
*/
private DictDesc dict;
/**
* 构造方法
*
* @param dict 字典描述
*/
public DictDescSerializer(DictDesc dict) {
this.dict = dict;
}
@Override
public JsonSerializer> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
DictDesc dict = property.getAnnotation(DictDesc.class);
if (dict != null) {
return new DictDescSerializer(dict);
}
return this;
}
/**
* Method that can be called to ask implementation to serialize
* values of type this serializer handles.
*
* @param value Value to serialize; can not be null.
* @param gen Generator used to output resulting Json content
* @param provider Provider that can be used to get serializers for
* http:// serializing Objects value contains, if any.
*/
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
provider.defaultSerializeValue(value, gen);
if (dict != null) {
String fieldName = gen.getOutputContext().getCurrentName();
// 添加转换之后的字段:xxxDesc
gen.writeStringField(fieldName.concat(LABEL_SUFFIX), DictDescSerializerUtils.getDesc(dict, fieldName, value));
}
}
}
字典序列化与反序列工具类
import cn.hutool.extra.spring.SpringUtil;
import com.aimilin.common.core.pojo.system.SysDict;
import com.aimilin.common.dict.annotation.DictDesc;
import com.aimilin.common.dict.annotation.DictEnum;
import com.aimilin.common.dict.exception.DictException;
import com.aimilin.common.dict.exception.enums.DictExceptionEnum;
import com.aimilin.common.dict.service.SysDictService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
* 字典转换工具类
*
* @author liujunguang1
* @version V1.0
* @date 2022/5/20 23:19
*/
@Slf4j
public class DictDescSerializerUtils {
/**
* 获取字典信息
*
* @param dict 字典对象
* @param value 字典值
* @return
*/
public static String getDesc(DictDesc dict, String field, Object value) {
if (ArrayUtils.isEmpty(dict.dictType()) && ArrayUtils.isEmpty(dict.enumType())) {
throw new DictException(DictExceptionEnum.REQUEST_DICT_TYPE, field);
}
try {
if (value == null) {
throw new DictException(DictExceptionEnum.REQUEST_NOT_NULL, field);
}
if (ArrayUtils.isNotEmpty(dict.enumType())) {
return getEnumDesc(dict, field, value);
}
return getDictDesc(dict, field, value);
} catch (Exception e) {
log.error("字典转换异常, field:{}, enumType:{}, dictType:{}, 值:{}, 异常:{}",
field, dict.enumType(), dict.dictType(), value, e.getMessage(), e);
if (dict.throwException()) {
throw e instanceof DictException ? (DictException) e : new DictException(DictExceptionEnum.DICT_EXCEPTION, e);
}
return dict.defaultValue();
}
}
/**
* 获取枚举类型的描述信息
*
* @param dict 字典
* @param value 值
* @return 枚举desc字段
*/
public static String getEnumDesc(DictDesc dict, String field, Object value) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
for (Class extends Enum extends DictEnum>> dictEnum : dict.enumType()) {
Method getCode = dictEnum.getMethod("getCode");
Method getMessage = dictEnum.getMethod("getMessage");
for (Enum extends DictEnum> e : dictEnum.getEnumConstants()) {
if (value.equals(getCode.invoke(e))) {
return Objects.toString(getMessage.invoke(e));
}
}
}
throw new DictException(DictExceptionEnum.UNKNOWN_ENUM_DICT_VALUE,
String.format("Field:%s, EnumType: %s, Value: %s", field, Arrays.toString(dict.enumType()), value));
}
/**
* 获取字典中的值
*
* @param dict 字典注解
* @param value 属性值
* @return 字典名称
*/
public static String getDictDesc(DictDesc dict, String field, Object value) {
if (ArrayUtils.isEmpty(dict.dictType())) {
throw new DictException(DictExceptionEnum.REQUEST_DICT_TYPE, field);
}
List
if (CollectionUtils.isEmpty(sysDictList)) {
throw new DictException(DictExceptionEnum.NO_DICT_DATA, field, Arrays.toString(dict.dictType()));
}
for (SysDict sysDict : sysDictList) {
if (StringUtils.equals(sysDict.getCode(), Objects.toString(value))) {
return sysDict.getValue();
http:// }
}
throw new DictException(DictExceptionEnum.UNKNOWN_DICT_VALUE, field, Arrays.toString(dict.dictType()));
}
}
字典转换服务类
/**
* 字典服务类
*
* @author liujunguang1
* @version V1.0
* @date 2022/5/20 16:03
*/
public interface SysDictService {
/**
* 根据字典类型code获取字典列表
*
* @param dictTypeCodes 字典类型code
* @return List
*/
public List
}
服务实现类:
/**
* 系统字典服务实现类
*
* @author liujunguang1
* @version V1.0
* @date 2022/5/20 16:13
*/
@Service
public class SysDictServiceImpl implements SysDictService {
@Resource
private SystemContextServiceApi systemContextServiceApi;
@Resource
private SysDictCache sysDictCache;
/**
* 根据字典类型编码获取字典数据
*
* @param dictTypeCodes 字典类型编码值
* @return List
*/
@Override
public List
List
if (CollectionUtils.isNotEmpty(dictTypeCache)) {
return dictTypeCache;
}
return systemContextServiceApi.getDictByDictTypeCode(dictTypeCodes).getData();
}
}
字典缓存服务
可以修改为使用本地缓存方式
/**
* 字典缓存服务
*
* @version V1.0
* @date 2022/5/19 12:13
*/
@Slf4j
@Service
public class SysDictCache {
@Resource
private RedisService redisService;
/**
* 获取字典类型缓存
*
* @param dictTypes 字典类型
* @return 字典列表
*/
public List
if (Objects.isNull(redisService)) {
log.info("redisService 为空,不使用字典缓存");
return null;
}
List> dictValues = redisService.getMultiCacheMapValue(CommonConstant.DICT_CACHE_KEY, Arrays.asList(dictTypes));
if (CollectionUtils.isEmpty(dictValues)) {
return null;
}
List
dictValues.stream().filter(Objects::nonNull).forEach(result::addAll);
log.debug("查询字典缓存,dictTypes:{}, 结果:{}", dictTypes, result);
return result;
}
/**
* 清空字典类型缓存
*
* @param dictTypes 字典类型
*/
public void cleanDictTypeCache(String... dictTypes) {
if (Objects.isNull(redisService)) {
return;
}
redisService.deleteCacheMapValue(CommonConstant.DICT_CACHE_KEY, dictTypes);
log.info("清除字典缓存,dictTypes:{}", StringUtils.join(dictTypes));
}
/**
* 添加缓存
*
* @param sysDictList 系统字典列表
*/
public void putDictTypeCache(List
if (Objects.isNull(redisService) || CollectionUtils.isEmpty(sysDictList)) {
return;
}
Map
for (Map.Entry
redisService.setCacheMapValue(CommonConstant.DICT_CACHE_KEY, entry.getKey(), entry.getValue());
log.info("设置字典缓存,dictType:{},结果:{}", entry.getKey(), entry.getValue());
}
}
}
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~