Когда наш проект предполагает мультиязычную поддержку,Разработано задней частью,интерфейсданныеинтернационализация
Это проблема, которую мы должны преодолеть。
иSpringBoot
обеспечивает мощныйинтернационализация(i18n)поддерживать,Позволяет разработчикам предоставлять индивидуальные текстовые ресурсы для разных регионов.
Тогда давай сделаем это вместе «Разорвите завесу интернационализации интерфейсных данных»,Узнайте больше о том, как SpringBoot
Внедрите интернационализацию в приложениях для удовлетворения многоязычных потребностей пользователей по всему миру.
Интернационализация, также называемая i18n, почему она называется i18n?
Это потому, что английское слово, обозначающее интернационализацию, — интернационализация, а между i и n 18 слов. Как и в наших k8, между k и s 8 слов (очень непринужденно🥰)
одинвеб-сайтилиприложение
,Первоначально он предоставлял услуги только отечественным пользователям.,Отображение страницыи Различные советы по эксплуатациитолько китайский язык。Позже с егоБизнес расширяется, добавляется больше функций, пользователей становится все больше.,Начинаем двигаться к международной платформе,тогда этоТип пользователяНе только отечественный,Может быть Франция、США、Пользователи из Японии и др. наций.
нравиться Если в это времявеб-сайтилиприложение
изпоказыватьи Различные операции по-прежнему выполняются на китайском языке.(илитолько одна странаязык),Потом другоенация Пользователи могут полностьюне могу читатьвеб-сайтилиприложение
или ВОЗТрудно работать。
Так сильно ли снизится его удобство для клиентов? Будет ли невозможно удержать таких клиентов?
Итак, для этого сценария сейчасинтернационализация
Это очень важно。
Для нашего проекта,интернационализация
Можно разделить на фронтендизадняя часть Две части:
Интернационализация внешнего интерфейса:
Интернационализация внешнего интерфейса в основном фокусируется на отображении страниц и локализации пользовательского интерфейса. Он включает в себя перевод и адаптацию элементов интерфейса приложения, таких как текст, метки, кнопки и т. д., к языку и региону пользователя. Интерфейсная интернационализация обычно использует файлы ресурсов, языковые пакеты или службы перевода для хранения текста на разных языках и управления им. Разработчики внешнего интерфейса могут реализовывать функции интернационализации внешнего интерфейса с помощью фреймворков или библиотек интернационализации, таких как React Intl, Vue I18n или Angular i18n.
Интернационализация серверной части:
Внутренняя интернационализация в основном фокусируется на решении проблем интернационализации, связанных с бизнес-логикой и данными. Сюда входят, помимо прочего, форматы даты и времени, символы валют, числовые форматы, правила сортировки, подсказки интерфейса и т. д. Цель интернационализации серверной части — обеспечить возможность адаптации приложения к различным языкам и регионам и предоставление правильных локализованных данных. Интернационализация серверной части может быть достигнута с помощью библиотек или фреймворков интернационализации, таких как SpringBoot I18n.
Короче говоря, интернационализация внешнего интерфейса в основном фокусируется на локализации отображения страниц и пользовательского интерфейса, тогда как интернационализация внутреннего интерфейса занимается вопросами интернационализации, связанными с бизнес-логикой и данными. Для достижения полной функциональности интернационализации обычно необходимо работать вместе.
Прежде чем мы начнем интернационализировать внутренний интерфейс, давайте сначала разберемся с некоторыми базовыми знаниями.
нуждатьсяподдерживатьинтернационализация,Сначала вы должны знать, какой регион и язык вы выбираете.,javaиспользуется вjava.util.Locale
ПриходитьУказывает региональный язык,Этот объект содержит информацию о нациязык.
Наиболее часто используемые методы построения в Locale:
public Locale(String language, String country) {
this(language, country, "");
}
Конструктор имеет два параметра:language:язык、country:нация
Значения этих двух параметров пишутся не случайно.,На международном уровне существуют единые стандарты.,нравиться:zh-CNвыражатьМатериковый Китайрегиональный китайский,zh-TWвыражатьТайвань, Китайрегиональный китайский,en-USвыражатьрегион СШАпо-английски,en-GBвыражатьрегион Великобританиипо-английскии т. д.。проходитьязыкинацияструктура Объект локали,Сравниватьнравиться
Locale locale = new Locale("zh", "CN");
,выражать Материковый Китайцы в регионе Китая.
Многие часто используемые объекты Locale созданы в классе Locale и могут использоваться напрямую. Давайте рассмотрим некоторые из них:
static public final Locale SIMPLIFIED_CHINESE = createConstant("zh", "CN");
static public final Locale TRADITIONAL_CHINESE = createConstant("zh", "TW");
static public final Locale FRANCE = createConstant("fr", "FR");
static public final Locale GERMANY = createConstant("de", "DE");
Это основной интерфейс интернационализации Spring, который определяется следующим образом:
public interface MessageSource {
/**
* Получите международную информацию
*/
@Nullable
String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale);
/**
* Аналогичен описанному выше методу, за исключением того, что если соответствующее имя атрибута в ресурсе не может быть найдено, исключение NoSuchMessageException создается напрямую.
*/
String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException;
/**
* @param MessageSourceResolvable Инкапсулируйте имя атрибута, массив параметров и информацию по умолчанию. Его функция такая же, как и у первого метода.
*/
String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
}
MessageSource
интерфейс Предусмотрено три приобретенияинтернационализацияметод сообщения,В основном оно основано на Locale информацию для получения соответствующего набора интернационализированных сообщений, а затем на основе code Получите соответствующее сообщение,ипроходитьпоставлятьизпараметр args Вы также можете отформатировать полученное сообщение.
Конкретные значения параметров следующие:
Имя параметра | значение |
---|---|
code | Представляет имя атрибута в интернационализированных ресурсах. |
args | Значения для заполнения параметров в сообщении |
defaultMessage | Сообщение по умолчанию, если не найдено, будет возвращено сообщение по умолчанию. |
resolvable | Параметры сообщения, инкапсулирующий код, аргументы, defaultMessage |
locale | Представляет объект локализации |
Три общих класса реализации:
Имя класса | значение |
---|---|
ResourceBundleMessageSource | Это основано на реализации базового класса Java ResourceBundle, позволяющей загружать интернационализированные файлы только через имена ресурсов. |
ReloadableResourceBundleMessageSource | Эта функция аналогична функции первого класса с добавлением функции запланированного обновления, позволяющей обновлять информацию интернационализированных файлов без перезапуска системы. |
StaticMessageSource | Это позволяет программно предоставлять интернационализированную информацию. |
Ключевой момент: В проекте мы создадим MessageSource, но независимо от того, какой класс реализации или наш пользовательский класс используется, для имени компонента должно быть установлено значениеmessageSource
При загрузке ApplicationContext автоматически выполняется поиск bean-компонента MessagesSource, определенного в контексте (имя должно быть messageSource). Если источник сообщения не найден, создается пустой экземпляр messageSource.
Этот интерфейс используется для установки языка интернационализации по умолчанию для текущего сеанса. Он определяется следующим образом:
public interface LocaleResolver {
/**
* Анализ информации о локализации текущего запроса на основе текущего запроса.
*/
Locale resolveLocale(HttpServletRequest request);
/**
* Установите информацию о локализации текущего запроса и ответа.
*/
void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale);
}
resolveLocale
метод используется для изменения текущегоrequestВ анализе соответствующиеLocale
объект,Такие сценарии, как:
Например, когда в программу (сервер) отправляется запрос, как мы узнаем, из какой он страны? Нужно ли нам получать IP-адрес через запрос, а затем анализировать его в соответствующем регионе на основе IP-адреса? Нет, нет, это будет слишком много хлопот.
Интерфейс LocaleResolver, предоставляемый Spring, используется для анализа региона, используемого клиентом. Мы можем передать соответствующий язык в заголовке запроса или URL-адресе запроса, а LocaleResolver может создать соответствующий объект Locale в соответствии с правилами.
Существует 4 общих класса реализации:
Имя класса | значение |
---|---|
AcceptHeaderLocalResovler | проходить Заголовок запросавнутри |
CookieLocaleResovler | Определите конкретный локализованный экземпляр локали на основе определенного параметра, установленного пользователем в файле cookie. |
SessionLocaleResovler | Определите конкретный локализованный экземпляр Locale в соответствии с определенным параметром, установленным пользователем в HttpSession. |
FixedLocalResovler | Используйте экземпляр Locale по умолчанию, который поставляется с jdk. |
В проекте,существоватьresources
Создайте каталог с именемi18n
каталог файлов,тогда мысуществоватьi18n
Создание каталогафайлы интернационализации
Формат::имя_язык_область.properties
Давайте сначала создадим два языка, например:
message.properties
name=ваше имя
текст = текст по умолчанию
В этом имени файла не указана локальная информация. Если система не может его найти, она будет использовать имя по умолчанию.
message_cn_ZH.properties: китайский [Китай]
имя=имя
текст=текст
message_en_GB.properties: английский [Великобритания]
name=Full name
text=text
наспроходитьMessageSource
интерфейсизgetMessage
методвходящийверноотвечатьизkey
(нравитьсяnaem、text),Тогда ты сможешьфайлы Возьмите ценность от интернационализации. В то же время мы также можем указать Объект локали, вы можете найти соответствующие файлы интернационализации Затем получите значение。
в растворе,приметВ то же время прочитайте информацию о интернационализации из базы данных и файла свойств.,достигатьинтернационализация Высокая информационная гибкость。
существоватьresources/i181n/messages
Оглавление,Создайте три файла отдельно(keyизимярекомендоватьНапишите с большой буквы и подчеркнитеиз Способ)
message.properties:
OK_NAME=ваше имя
OK_TEXT=Текст по умолчанию
В этом имени файла не указана локальная информация. Если система не может его найти, она будет использовать имя по умолчанию.
message_cn_ZH.properties: китайский [Китай]
OK_NAME=Имя
OK_TEXT=Текст
message_en_GB.properties: английский [Великобритания]
OK_NAME=Full name
OK_TEXT=text
Укажите путь к файлу интернационализации i18n:
spring:
messages:
basename: i18n/messages
encoding: UTF-8
Содержимое таблицы (таблица просто создается, вы можете ее улучшить самостоятельно):
CREATE TABLE `ok_i18message` (
`code` varchar(255) NOT NULL COMMENT 'Имя атрибута',
`locale` varchar(100) DEFAULT NULL COMMENT 'код нации',
`message` varchar(255) DEFAULT NULL COMMENT «Соответствующее содержание»,
PRIMARY KEY (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Данные таблицы:
INSERT INTO `ok_i18message` (`code`, `locale`, `message`) VALUES ('OK_PASSWORD', 'cn_ZH', 'пароль');
INSERT INTO `ok_i18message` (`code`, `locale`, `message`) VALUES ('OK_PASSWORD', 'en_GB', 'password');
INSERT INTO `ok_i18message` (`code`, `locale`, `message`) VALUES ('OK_AGE', 'cn_ZH', 'возраст');
INSERT INTO `ok_i18message` (`code`, `locale`, `message`) VALUES ('OK_AGE', 'en_GB', 'age');
Класс сущности:
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Таблица интернационализации
* @ClassName I18message
* @Author Blue
* @Date 2023/11/5
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("ok_i18message")
@ApiModel(description = "Таблица интернационализации")
public class I18message {
@ApiModelProperty("имя свойства")
private String code;
@ApiModelProperty("нациякод") private String locale;
@ApiModelProperty("соответствующее содержимое")
private String message;
}
класс картографа:
import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* Таблица интернационализации
* @ClassName AssetsLogMapper
* @Author Blue
* @Date 2023/11/5
*/
@Mapper
public interface I18messageMapper extends MPJBaseMapper<I18message> {
}
Случай:использовать
mybatis-plus
Приходить Заканчиватьверноповерхностьизcrud
насиспользовать Пользовательский класс MessageSourceПриходить Интегрироватьинтернационализацияинформация,существовать
3.2 MessageSourceинтерфейс
Есть поговоркаStaticMessageSource
выполнитьдобрый Можетпроходитьпрограммированиеиз Способпоставлятьинтернационализацияинформация,Так почему бы нам просто не использовать его? Но настроить класс? Объяснение я оставил напоследок.
Исходный код сообщения:
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.context.support.AbstractMessageSource;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
// @Component("messageSource"): Вы также можете указать здесь имя bean-компонента как messageSource
public class MyMessageSource extends AbstractMessageSource implements InitializingBean {
// Внедрить объект интерфейса запроса
@Resource
private I18messageMapper i18messageMapper;
/**
* Это используется для кэширования конфигурации, полученной из базы данных.
* Когда конфигурация базы данных изменится, вы можете вызвать метод reload для перезагрузки.
*/
private static final Map<String, Map<String, String>> LOCAL_CACHE = new ConcurrentHashMap<>();
/**
* После запуска программы она автоматически загрузится
*/
@Override
public void afterPropertiesSet() {
this.reload();
}
/**
* Перезагрузить сообщения в кэш карты класса.
*/
public void reload() {
// Очистить кеш этого класса
LOCAL_CACHE.clear();
// Загрузить все интернационализированные ресурсы
LOCAL_CACHE.putAll(this.loadAllMessageResources());
}
/**
* Цель: загрузить все интернационализированные ресурсы сообщений.
* В то же время прочитайте информацию о интернационализации из базы данных и файла свойств.
*/
private Map<String, Map<String, String>> loadAllMessageResources() {
// Запросить все международные ресурсы из базы данных
List<I18message> allLocaleMessage = i18messageMapper.selectList(null);
if (ObjectUtils.isEmpty(allLocaleMessage)) {
allLocaleMessage = new ArrayList<>();
}
// Преобразуйте запрошенные международные ресурсы в Map<областькод, Map<code, информация>> формат данных
Map<String, Map<String, String>> localeMsgMap = allLocaleMessage
// транслировать
.stream()
// Группа
.collect(Collectors.groupingBy(
// в соответствии снацияобласть Группа
I18message::getLocale,
// Собрано как карта, ключ — это код, значение — информация.
Collectors.toMap(
I18message::getCode
, I18message::getMessage
)
));
// Получить список регионов страны
List<Locale> localeList = localeMsgMap.keySet().stream().map(Locale::new).collect(Collectors.toList());
for (Locale locale : localeList) {
// Читайте локальные интернационализированные файлы ресурсов в соответствии с национальным регионом. Наши интернационализированные файлы ресурсов размещаются в папке i18n.
ResourceBundle resourceBundle = ResourceBundle.getBundle("i18n/messages", locale);
// Получите ключ-значение в интернационализированном файле ресурсов.
Set<String> keySet = resourceBundle.keySet();
// Воля код=информация Формат сбора данных: Map<code,информация> формат
Map<String, String> msgFromFileMap = keySet.stream()
.collect(
Collectors.toMap(
Function.identity(),
resourceBundle::getString
)
);
// Воляместныйизинтернационализацияинформацияиданныебиблиотекаизинтернационализацияинформацияслить
Map<String, String> localeFileMsgMap = localeMsgMap.get(locale.getLanguage());
localeFileMsgMap.putAll(msgFromFileMap);
localeMsgMap.put(locale.getLanguage(), localeFileMsgMap);
}
return localeMsgMap;
}
/**
* Загрузка интернационализированных ресурсов в кэш-карту
*/
private String getSourceFromCacheMap(String code, Locale locale) {
String language = ObjectUtils.isEmpty(locale)
? LocaleContextHolder.getLocale().getLanguage() : locale.getLanguage();
// Получить все элементы данных, соответствующие языку, в кеше.
Map<String, String> propMap = LOCAL_CACHE.get(language);
if (!ObjectUtils.isEmpty(propMap) && propMap.containsKey(code)) {
// Если элемент данных может быть сопоставлен на соответствующем языке, вернитесь напрямую.
return propMap.get(code);
}
// Если интернационализированное сообщение не может быть найдено, код будет возвращен напрямую.
return code;
}
/**
* Метод реализации для внутреннего использования метода getMessage
*/
@Override
protected MessageFormat resolveCode(String code, Locale locale) {
String msg = this.getSourceFromCacheMap(code, locale);
return new MessageFormat(msg, locale);
}
/**
* Метод реализации для внутреннего использования метода getMessage
*/
@Override
protected String resolveCodeWithoutArguments(String code, Locale locale) {
return this.getSourceFromCacheMap(code, locale);
}
}
Мы настроилиMyMessageSource
класс наследуетAbstractMessageSource
абстрактныйдобрый и ОсуществленныйInitializingBean
интерфейс,оти ОсуществленныйотИнтернационализированные сообщения, полученные из базы данныхиСообщения интернационализации в локальных файлах свойствИнтегрироватьиз Функция。
имя | значение |
---|---|
AbstractMessageSource | Абстрактный класс наследует интерфейс HierarchicalMessageSource, который, в свою очередь, наследует MessageSource. Это абстрактный класс, поддерживающий метод «файла конфигурации». Он предоставляет общедоступный файл конфигурации сообщения, который не имеет ничего общего с настройками локали. Код сообщения является ключевым словом. |
InitializingBean | Предоставляет метод инициализации для bean-компонентов. Он включает только метод afterPropertiesSet. Все классы, наследующие этот интерфейс, будут выполнять этот метод при инициализации bean-компонента. |
Возможно, вы заметили,нассуществоватьнаследоватьAbstractMessageSource
абстрактныйдобрый Позже переписал дваметод:resolveCode
、resolveCodeWithoutArguments
,Эти два метода предназначены дляgetMessage
методвнутреннийиспользоватьиз。
мы входимAbstractMessageSource
Исходный код,ПроверятьgetMessage
метод,существоватьвызовэто时входящийcode
иlocale
,оно позвонитresolveCode
методили ВОЗвызовresolveCodeWithoutArguments
методполучитьинформация,в конце концов вернутьсяверноотвечатьизинтернационализацияинформация。
Эти два метода были переписаны нами.,этоизданные都отнас自定义изMyMessageSource
добрыйизLOCAL_CACHE(объект карты)
Залезай,
LocaleResolver:использовать Приходить Установить текущий сеанс по умолчаниюизинтернационализацияязык
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
/**
* преобразователь локали
* @ClassName MyLocaleResolver
* @Author Blue
* @Date 2023/11/6
*/
@Configuration
public class MyLocaleResolver implements LocaleResolver {
/**
* Анализ информации о локализации текущего запроса на основе текущего запроса.
*/
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
// Запросить параметры URL
String l = httpServletRequest.getParameter("lang");
// Параметры заголовка запроса
String header = httpServletRequest.getHeader("lang");
// Интернационализация: каждый объект локали представляет определенную политическую культуру, регион и метод создания.
Locale locale = null;
// суждение Запросить параметры Есть ли в URL-адресе параметр lang (предпочтительно)
if (!StrUtil.isEmpty(l)) {
// Разделить по подчеркиванию
String[] split = l.split("_");
// Создание международных объектов
locale = new Locale(split[0], split[1]);
// суждение Параметры заголовка Есть ли в запросе параметр lang?
} else if(!StrUtil.isEmpty(header)) {
// Заменить пустым
header = header.replaceAll("\"","");
// Разделить по подчеркиванию
String[] split = header.split("_");
// Создание международных объектов
locale = new Locale(split[0], split[1]);
}
return locale;
}
/**
* Установите информацию о локализации текущего запроса и ответа.
*/
@Override
public void setLocale(HttpServletRequest httpServletRequest, @Nullable HttpServletResponse
httpServletResponse, @Nullable Locale locale) {
}
}
здесьиз Ключевым моментом являетсясуществовать В:Волянас自定义изMyMessageSource
добрый,Оставьте это контейнеру Spring для создания и управления.,иимяустановлен наmessageSource
。
/**
* Web Mvc Конфигуратор
* Решайте междоменные проблемы, добавляйте перехватчики, настраивайте преобразователи представлений, обработку статических ресурсов, интернационализацию и т. д.
* @ClassName ApplicationConfig
* @Author Blue
* @Date 2023/11/5
*/
@Configuration
public class ApplicationConfig implements WebMvcConfigurer {
/**
* преобразователь локали
*/
@Bean
public LocaleResolver localeResolver() {
return new MyLocaleResovel();
}
/**
* Когда Spring запускается и загружает контекст, он запрашивает, существует ли bean-компонент с именем контейнера в качестве messageSource.
* В противном случае будет создан компонент с именем messageSource и помещен в контекст.
* Мы вручную создаем bean-компонент с именем messageSource вместо того, чтобы Spring создавал его автоматически.
*/
@Bean
public MessageSource messageSource() {
return new MyMessageSource();
}
}
верноMessageSource
Инкапсулировать,Нам удобно пользоваться
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import java.util.Locale;
/**
* Служба источника сообщений локали
* @ClassName LocaleMessageSourceService
* @Author Blue
* @Date 2022/11/14
*/
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class LocaleMessageSourceService {
private final MessageSource messageSource;
/**
* @param code Ключ, соответствующий конфигурации сообщений
* @return String
*/
public String getMessage(String code){
return getMessage(code,null);
}
/**
* @param code Ключ, соответствующий конфигурации сообщений
* @param args Параметры массива
* @return String
*/
public String getMessage(String code,Object[] args){
return getMessage(code, args,"");
}
/**
* @param code Ключ, соответствующий конфигурации сообщений
* @param args Параметры массива
* @param defaultMessage Значение по умолчанию, если ключ не установлен
* @return String
*/
public String getMessage(String code,Object[] args,String defaultMessage){
Locale locale = LocaleContextHolder.getLocale();
return messageSource.getMessage(code, args, defaultMessage, locale);
}
}
Есть много способов сказать Сценарии использования,нравитьсяВзаимодействие с валидатором проверки параметров, глобальным исключением и информацией об интерфейсе.Возврат и так далее,Реальные проекты могут быть более сложными, поэтому я здесь для того, чтобы использовать его просто для того, чтобы каждый мог использовать его самостоятельно.。
/**
* глобальное обработчик файлов
* @ClassName GlobalExceptionHandler
* @Author Blue
* @Date 2023/11/6
*/
@Slf4j
@RestControllerAdvice
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class GlobalExceptionHandler {
private final LocaleMessageSourceService localeMessageSourceService;
/**
* Пользовательская обработка исключений проверки
* Советы по безопасности интернационализации-проверка-jsr303
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
log.error(e.getMessage(), e);
// Получите значение ключа, соответствующее решению параметра безопасности.
String message = e.getBindingResult().getFieldError().getDefaultMessage();
return Result.fail(message);
}
/**
* Пользовательская обработка исключений проверки
* Assert - Обработка исключений
*/
@ExceptionHandler(IllegalArgumentException.class)
public Result handleIllegalArgumentException(IllegalArgumentException e) {
log.error(e.getMessage(), e);
// Параметры метода getMessage заполняются соответствующим образом. файлы интернационализации или Таблица интернационализации Просто код в
return Result.fail(localeMessageSourceService.getMessage("OK_NAME"));
}
/**
* Пользовательская обработка исключений проверки
* Ошибка формата электронной почты
*/
@ExceptionHandler({MailSendException.class,SendFailedException.class,SMTPAddressFailedException.class})
public Result handleMailSendException(Exception e) {
log.error(e.getMessage(), e);
// Параметры метода getMessage заполняются соответствующим образом. файлы интернационализации или Таблица интернационализации Просто код в
return Result.fail(localeMessageSourceService.getMessage("OK_AGE"));
}
/**
* Пользовательская обработка исключений проверки
* Возможно, WebSocketServer неправильно отправил сообщение.
*/
@ExceptionHandler(IOException.class)
public Result handleIOException(IOException e) {
log.error(e.getMessage(), e);
// Параметры метода getMessage заполняются соответствующим образом. файлы интернационализации или Таблица интернационализации Просто код в
return Result.fail(localeMessageSourceService.getMessage("OK_WS_ERROR"));
}
/**
* все Обработка исключений
*/
@ExceptionHandler
public Result handlerException(Exception e) {
log.error(e.getMessage(), e);
return Result.fail(localeMessageSourceService.getMessage("OK_ERROR"));
}
}
@Slf4j
@CrossOrigin
@RefreshScope
@RestController
@Api(tags = «Тестовый интерфейс возвращает информацию о интернационализации»)
@RequestMapping("/test")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class TestController {
private final LocaleMessageSourceService localeMessageSourceService;
private final MyMessageSource myMessageSource;
@ApiOperation("Безопасность параметров")
@PostMapping("/is")
public Result is(String password,Integer age) {
if (StrUtil.isBlank(password)) {
return Result.fail(localeMessageSourceService.getMessage("OK_PASSWORD"));
}
if (ObjectUtil.isEmpty(age)) {
return Result.fail(localeMessageSourceService.getMessage("OK_AGE"));
}
// бизнес...
return Result.succeed("succeed");
}
@ApiOperation("Перезагрузить интернационализированные сообщения")
@PostMapping("/reloadMessage")
public void reloadMessage() {
myMessageSource.reload();
}
}
Конечно, мне нет нужды судить подобным образом о безопасности параметров.,слишком долго,Я просто хочу выразить сцену более интуитивно.,Каждый может объединитьВалидатор проверки параметров
,Одна аннотация может обеспечить безопасность параметров.интернационализациянамекать。
Здесь я напишу только два типа Сценариев. использования,Каждый может попробовать,Объедините свой бизнес и идеи,Сделайте свой код более мощным и простым в использовании!
существовать4.3 Пользовательский класс MessageSource
Почему мы должны Пользовательский класс MessageSourceШерстяная ткань?StaticMessageSource
добрый明明Может Это позволяет программно предоставлять интернационализированную информацию.
Вот почему:
StaticMessageSource
добрый也能выполнить同样из Функция,Однако его не рекомендуется использовать в производственной среде.,и НетподдерживатьинтернационализацияинформацияудалитьStaticMessageSource
Подходящийинтернационализацияинформациятест,поддерживать硬编кодизметоддобавить винтернационализацияинформацияКогда мы посмотрим на его исходный код, мы увидим:
Исходный кодиз В аннотации также упоминается:Intended for testing rather than for use in production systems.
В переводе на китайский язык этоИспользуется для тестирования, а не для производственных систем.
И все интернационализированные сообщения в конечном итоге будут кэшироваться в messageMap. Поскольку StaticMessageSource не предоставляет метода очистки данных карты, только при перезапуске программы интернационализированные сообщения, удаленные из базы данных, могут быть отражены в messageMap.
хорошо,До сих пор,насизПоиграйтесь с интернационализацией взаимодействия данных внутреннего интерфейса с нуля
конец,Я надеюсь, что каждый сможет что-то получить!
Если у вас есть какие-либо вопросы или вам нужна помощь по этой статье, оставьте сообщение в области комментариев, и я постараюсь ответить на него. Если эта статья была для вас полезна, пожалуйста, поставьте лайк в знак вашей поддержки, большое спасибо! 💗
Я участвую в третьем этапе специального тренировочного лагеря Tencent Technology Creation 2023 с эссе, получившими приз, и сформирую команду, которая разделит приз!