目次
シリアル化とは
シリアル化を使用して辞書値の変換を実現する
ホームページ Java &#&チュートリアル Java で辞書翻訳をエレガントに実装する方法

Java で辞書翻訳をエレガントに実装する方法

May 12, 2023 pm 05:31 PM
java

シリアル化とは

Java では、シリアル化とは、ファイルに保存したりネットワーク経由で送信したりできるバイト ストリームにオブジェクトを変換するプロセスです。逆シリアル化は、バイト ストリームを生のオブジェクトに変換するプロセスです。シリアル化と逆シリアル化を通じて、異なるアプリケーション間でオブジェクトを受け渡したり、後で使用するためにオブジェクトをファイルに保存したりすることもできます。

シリアル化を使用して辞書値の変換を実現する

Java では、シリアル化メカニズムを使用して、エンコーディングとそれに対応する意味の間の対応を実現できます。具体的な手順は次のとおりです:

1. 辞書アノテーションを定義します (例:

@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. カスタム アノテーションを継承する JsonSerialize と組み合わせて ContextualSerializer を実装し、返されたアノテーションの翻訳を実現します)結果:

@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. 同じタイプの辞書コードと対応する意味をマップに保存します (例:

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)。シリアル化では各オブジェクトがシーケンス操作を実行する必要があるため、コレクションが返されると、多くのシリアル化操作が実行されます。このとき、同じ型の辞書をキャッシュする必要があります。ローカル キャッシュには guava の LoadingCache を使用しました (この時点で辞書の値の意味が変更されると誰かがここで言うかもしれません) , キャッシュによって不正なデータが発生しませんか? まず、辞書機能は通常、管理側で追加、削除、変更が行われ、一度設定された辞書は簡単には変更されません。戦い、あなたが勝ちます)。

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;
                }
            });
}
ログイン後にコピー

ここでちょっとした知識を追加します:

  • expireAfterWrite と ExpireAfterAccess はどちらも、Google Guava キャッシュ ライブラリのキャッシュ有効期限戦略です。

  • expireAfterWrite は、キャッシュ アイテムがアクセスされたかどうかに関係なく、指定された時間が経過するとキャッシュ アイテムが期限切れになることを示します。たとえば、キャッシュ項目のexpireAfterWriteを10分に設定した場合、キャッシュ項目は、アクセスされたかどうかに関係なく、キャッシュに追加されてから10分後に期限切れになります。

  • これら 2 つの有効期限戦略を単独で使用することも、組み合わせて使用​​して、より柔軟なキャッシュ戦略を実現することもできます。たとえば、キャッシュ アイテムの期限切れ後書き込みを 10 分に設定し、期限切れ後アクセスも 5 分に設定すると、キャッシュ アイテムは 10 分後に期限切れになるか、過去 5 分間アクセスされなかった場合に期限切れになるかのどちらか早い方になります。 。

  • expireAfterWrite とexpirateAfterAccess を使用すると、キャッシュ内のデータの有効期限が長すぎたり短すぎたりすることを回避できるため、キャッシュの効率と信頼性が向上します。

5. aop アスペクト メソッドを使用する場合と比較して、シリアル化メソッドを使用すると、辞書をより適切に翻訳できます (aop メソッドはオブジェクトの属性を処理するのが難しいため)。次に例を示します。

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

public class Staff {
  private Integer age;
  private String name;
  @Dic(dic = "position")
  private String position;
  
}
ログイン後にコピー

このシナリオでは、Company コレクションが返された場合、aop アスペクト方式を使用したシリアル化方式と同じ効果 (開発難易度および開発コスト) を達成することは困難になります。

上記の手順により、Java のシリアル化メカニズムを使用して、辞書エンコーディングとそれに対応する意味の間の対応をエレガントに実現できるため、エンコードされたデータの管理と保守が簡素化されます。

以上がJava で辞書翻訳をエレガントに実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Javaの完全数 Javaの完全数 Aug 30, 2024 pm 04:28 PM

Java における完全数のガイド。ここでは、定義、Java で完全数を確認する方法、コード実装の例について説明します。

Java の乱数ジェネレーター Java の乱数ジェネレーター Aug 30, 2024 pm 04:27 PM

Java の乱数ジェネレーターのガイド。ここでは、Java の関数について例を挙げて説明し、2 つの異なるジェネレーターについて例を挙げて説明します。

ジャワのウェカ ジャワのウェカ Aug 30, 2024 pm 04:28 PM

Java の Weka へのガイド。ここでは、weka java の概要、使い方、プラットフォームの種類、利点について例を交えて説明します。

Javaのスミス番号 Javaのスミス番号 Aug 30, 2024 pm 04:28 PM

Java のスミス番号のガイド。ここでは定義、Java でスミス番号を確認する方法について説明します。コード実装の例。

Java Springのインタビューの質問 Java Springのインタビューの質問 Aug 30, 2024 pm 04:29 PM

この記事では、Java Spring の面接で最もよく聞かれる質問とその詳細な回答をまとめました。面接を突破できるように。

Java 8 Stream Foreachから休憩または戻ってきますか? Java 8 Stream Foreachから休憩または戻ってきますか? Feb 07, 2025 pm 12:09 PM

Java 8は、Stream APIを導入し、データ収集を処理する強力で表現力のある方法を提供します。ただし、ストリームを使用する際の一般的な質問は次のとおりです。 従来のループにより、早期の中断やリターンが可能になりますが、StreamのForeachメソッドはこの方法を直接サポートしていません。この記事では、理由を説明し、ストリーム処理システムに早期終了を実装するための代替方法を調査します。 さらに読み取り:JavaストリームAPIの改善 ストリームを理解してください Foreachメソッドは、ストリーム内の各要素で1つの操作を実行する端末操作です。その設計意図はです

Java での日付までのタイムスタンプ Java での日付までのタイムスタンプ Aug 30, 2024 pm 04:28 PM

Java での日付までのタイムスタンプに関するガイド。ここでは、Java でタイムスタンプを日付に変換する方法とその概要について、例とともに説明します。

カプセルの量を見つけるためのJavaプログラム カプセルの量を見つけるためのJavaプログラム Feb 07, 2025 am 11:37 AM

カプセルは3次元の幾何学的図形で、両端にシリンダーと半球で構成されています。カプセルの体積は、シリンダーの体積と両端に半球の体積を追加することで計算できます。このチュートリアルでは、さまざまな方法を使用して、Javaの特定のカプセルの体積を計算する方法について説明します。 カプセルボリュームフォーミュラ カプセルボリュームの式は次のとおりです。 カプセル体積=円筒形の体積2つの半球体積 で、 R:半球の半径。 H:シリンダーの高さ(半球を除く)。 例1 入力 RADIUS = 5ユニット 高さ= 10単位 出力 ボリューム= 1570.8立方ユニット 説明する 式を使用してボリュームを計算します。 ボリューム=π×R2×H(4

See all articles