您好,登錄后才能下訂單哦!
這篇文章主要介紹了Java怎么優雅的實現字典翻譯的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇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.將同類型的字典編碼和對應的含義保存到一個Map中,例如:
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分鐘后過期,無論它是否被訪問過。
這兩種過期策略可以單獨或組合使用,以實現更靈活的緩存策略。例如,我們可以將緩存項的expireAfterWrite設置為10分鐘,同時將expireAfterAccess設置為5分鐘,這樣緩存項將在10分鐘后過期,或者在最近5分鐘內沒有被訪問時過期,以先到者為準。
使用expireAfterWrite和expireAfterAccess可以避免緩存中的數據過期時間過長或過短,從而提高緩存的效率和可靠性。
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怎么優雅的實現字典翻譯”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“Java怎么優雅的實現字典翻譯”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。