Maison >Java >javaDidacticiel >Comment implémenter élégamment la traduction de dictionnaire en Java

Comment implémenter élégamment la traduction de dictionnaire en Java

PHPz
PHPzavant
2023-05-12 17:31:061482parcourir

Qu'est-ce que la sérialisation

En Java, la sérialisation est le processus de conversion d'objets en un flux d'octets qui peut être enregistré dans un fichier ou transmis sur un réseau. La désérialisation est le processus de conversion d'un flux d'octets en un objet brut. Grâce à la sérialisation et à la désérialisation, nous pouvons transmettre des objets entre différentes applications et également enregistrer des objets dans des fichiers pour une utilisation ultérieure.

Utilisez la sérialisation pour réaliser la traduction des valeurs du dictionnaire

En Java, nous pouvons utiliser le mécanisme de sérialisation pour réaliser la correspondance entre l'encodage et sa signification correspondante. Les étapes spécifiques sont les suivantes :

1. Définissez une annotation de dictionnaire, par exemple :

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = DictSerializer.class)
public @interface Dict {

    /**
     * 字典类型
     * 比如在描述学生的时候,1代表小学生 2代表初中生 3代表高中生 4代表大学生
     * 同样在描述老师的时候,1代表语文老师 2代表数学老师 3代表英语老师 4代表体育老师
     * 同样的数值在不同类型下,代表含义不同,所以需要指定字典的类型
     */
    String dic();
}

2 Combinez l'annotation personnalisée avec l'héritage de JsonSerialize pour implémenter ContextualSerializer, et réalisez la traduction des résultats renvoyés :

@Slf4j
public class DictSerializer extends StdSerializer<Object> implements ContextualSerializer {

    private transient String dictCode;

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty beanProperty){
        Dict dict = beanProperty.getAnnotation(Dict.class);
        return createContextual(dict.dic());
    }

    private JsonSerializer<?> createContextual(String dicCode) {
        DictSerializer serializer = new DictSerializer();
        serializer.setDictCode(dicCode);
        return serializer;
    }

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider provider){

        String dictCode = getDictCode();
        if (StrUtil.isBlank(dictCode)) {
            return;
        }
        if (Objects.isNull(value)) {
            return;
        }
        try {
            // 因为序列化是每个对象都需要进行序列话操作,这里为了减少网络IO,使用了 guava 的本地缓存(代码在下面)
            Map<String, String> dictMap = DictionaryConstants.DICTIONARY_CACHE.get(dictCode);
            if (dictMap.containsKey("nullValue")) {
                // 当本地缓存中不存在该类型的字典时,就调用查询方法,并且放入到本地缓存中(代码在下面)
                dictMap = translateDictValue(dictCode);
                DictionaryConstants.DICTIONARY_CACHE.put(dictCode, dictMap);
            }
            // 通过数据字典类型和value获取name
            String label = dictMap.get(value.toString());
            gen.writeObject(value);
            // 在需要转换的字段上添加@Dict注解,注明需要引用的code,后端会在返回值中增加filedName_dictText的key,前端只需要取对应的 filedName_dictText 就可以直接使用
            gen.writeFieldName(gen.getOutputContext().getCurrentName() + DictionaryConstants.DICT_TEXT_SUFFIX);
            gen.writeObject(label);
        } catch (Exception e) {
            log.error("错误信息:{}", e.getMessage(), e);
        }
    }

    private String getDictCode() {
        return dictCode;
    }

    private void setDictCode(String dictCode) {
        this.dictCode = dictCode;
    }

    protected DictSerializer() {
        super(Object.class);
    }
}

3. le même type de dictionnaire et sa signification correspondante Enregistrez-le dans une carte, par exemple :

private Map<String, String> translateDictValue(String code) {
    if (StrUtil.isBlank(code)) {
      return null;
    }
    // Map<String, String> map = new HashMap<>();
    // map.put("1", "小学生");
    // map.put("2", "初中生");
    // map.put("3", "高中生");
    // map.put("4", "大学生");
  
    // 因为我们公司采用微服务,然后字典模块单独拆分成一个服务,所以这里使用Feign方式调用
    DictionaryFeignClient dictionaryFeign = SpringUtil.getBean(DictionaryFeignClient.class);
    return dictionaryFeign.dictionary(code);
}

4. Parce que la sérialisation nécessite que chaque objet effectue une opération de sérialisation, si une collection est renvoyée, de nombreuses opérations de sérialisation seront effectuées dans ce cas. , le même type doit être Le dictionnaire est mis en cache. J'utilise LoadingCache de guava pour la mise en cache locale (quelqu'un peut dire ici que si la signification de la valeur du dictionnaire est modifiée à ce moment-là, votre cache ne conduira-t-il pas à des données incorrectes ? tout, la fonction dictionnaire est généralement Le côté gestion effectue les opérations d'ajout, de suppression et de modification, et une fois le dictionnaire défini, il ne sera pas facilement modifié. Si vous voulez vous battre dur, vous gagnez).

public class DictionaryConstants {

    /**
     * 字典翻译文本后缀
     */
    public static final String DICT_TEXT_SUFFIX = "_dictText";

    public static final LoadingCache<String, Map<String, String>> DICTIONARY_CACHE = CacheBuilder.newBuilder()
            .maximumSize(1000)
            .expireAfterWrite(30, TimeUnit.SECONDS)
            .expireAfterAccess(10, TimeUnit.SECONDS)
            .build(new CacheLoader<String, Map<String, String>>() {
                @Override
                public Map<String, String> load(String key) {
                    Map<String, String> map = new HashMap<>();
                    map.put("nullValue", "nullValue");
                    return map;
                }
            });
}

Voici une petite connaissance supplémentaire :

  • expireAfterWrite et expireAfterAccess sont toutes deux des stratégies d'expiration du cache dans la bibliothèque de cache Google Guava.

  • expireAfterWrite signifie que l'élément de cache expire après l'heure spécifiée, que l'élément de cache ait été ou non accédé. Par exemple, si nous définissons l'expirationAfterWrite de l'élément de cache sur 10 minutes, l'élément de cache expire 10 minutes après son ajout au cache, qu'il ait été accédé ou non.

  • Ces deux stratégies d'expiration peuvent être utilisées seules ou en combinaison pour obtenir une stratégie de mise en cache plus flexible. Par exemple, nous pouvons définir expireAfterWrite de l'élément de cache sur 10 minutes et également définir expireAfterAccess sur 5 minutes, de sorte que l'élément de cache expire après 10 minutes, ou expire lorsqu'il n'a pas été accédé au cours des 5 dernières minutes, selon la première éventualité. .

  • Utilisez expireAfterWrite et expireAfterAccess pour éviter que le délai d'expiration des données dans le cache ne soit trop long ou trop court, améliorant ainsi l'efficacité et la fiabilité du cache.

5. Par rapport à l'utilisation des aspects aop, l'utilisation de la sérialisation peut mieux traduire le dictionnaire (car il est difficile pour aop de gérer les propriétés des attributs dans les objets), par exemple :

public class Company {
  private List<Staff> staffs;
}

public class Staff {
  private Integer age;
  private String name;
  @Dic(dic = "position")
  private String position;
  
}

Ici Dans ce scénario, si l'entreprise Si la collection est renvoyée, il sera difficile d'obtenir le même effet (difficulté de développement et coût de développement) que la méthode de sérialisation utilisant la méthode d'aspect aop.

Grâce aux étapes ci-dessus, nous pouvons utiliser le mécanisme de sérialisation en Java pour réaliser avec élégance la correspondance entre l'encodage du dictionnaire et sa signification correspondante, simplifiant ainsi la gestion et la maintenance des données codées.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer