Vorwort
Das Unternehmen hat das Projekt von Struts2 auf SpringMVC übertragen. Da es sich bei dem Geschäft des Unternehmens in Überseediensten handelt, ist die Nachfrage nach internationalen Funktionen sehr hoch. Die Internationalisierungsfunktion von Struts2 ist perfekter als SpringMVC, aber das große Merkmal von Spring ist, dass es anpassbar und angepasst ist. Daher wird seine Internationalisierungsfunktion hinzugefügt, wenn das Projekt des Unternehmens auf SpringMVC transplantiert wird. Ich habe die Aufzeichnungen zusammengestellt und hier verbessert.
Die in diesem Artikel implementierten Hauptfunktionen:
Laden Sie mehrere internationale Dateien direkt aus einem Ordner. Auf der Front-End-Seite der Hintergrundeinstellung werden internationale Informationen angezeigt. Die Datei, in der internationale Informationen angezeigt werden, wird automatisch mit Interceptors und Anmerkungen festgelegt. Die Datei, in der internationale Informationen auf der Front-End-Seite angezeigt werden, zeigt internationale Informationen an.
Hinweis: Dieser Artikel führt nicht ausführlich mit der Konfiguration der Internationalisierung, des regionalen Parsers usw. ein.
erreichen
Internationale Projektinitialisierung
Erstellen Sie zunächst ein grundlegendes Spring-Boot+Thymeleaf+Internationalization Information (Message.Properties). Wenn Sie es brauchen, können Sie es von meinem GitHub herunterladen.
Ein kurzer Blick auf das Verzeichnis und die Dateien des Projekts
Unter ihnen legt i18napplication.java einen CookieLocaleResolver fest, der Cookies verwendet, um internationale Sprachen zu kontrollieren. Richten Sie auch einen LocaleChangeInterceptor -Interceptor ein, um Änderungen in internationalen Sprachen abzufangen.
@SpringBootApplication@configurationPublic Klasse I18NApplication {public static void main (String [] args) {SpringApplication.run (i18napplication.class, args); } @Bean public localeresolver localeresolver () {CookieloCaleresolver Slr = new CookieloCaleresolver (); slr.setcookiemaxage (3600); Slr.SetCookiename ("Sprache"); // Legen Sie den Namen des gespeicherten Cookie -to -Sprache zurück. } @Bean public webmvcconFigurer webmvcconFigurer () {return New WebMvcConFigurer () {// interceptor @überschrieben public void addInterceptors (interceptorRegistry -Registrierung) {Registry.Addinterceptor (neue localechangeInterinterce (). }}; }}Schauen wir uns an, was in hello.html geschrieben ist:
<! DocType html> <html xmlns = "http://www.w3.org/1999/xhtml" xmlns: th = "http://www.thymeleaf.org"> <Haart> <titels> Hallo Weltwelz! th: text = "#{i18n_page}"> </h1> <h3 th: text = "#{hello}"> </h3> </body> </html> Starten Sie nun das Projekt und besuchen Sie http://localhost:9090/hello (ich habe den Port auf 9090 in application.Properties festgelegt).
Da die Standardsprache des Browsers chinesisch ist, sucht sie standardmäßig in messus_zh_cn.properties, und wenn nicht, sucht sie in Nachrichten.Properties nach internationalen Wörtern.
Dann geben wir http://localhost:9090/hello?locale=en_US im Browser ein und die Sprache wird auf Englisch geschnitten. In ähnlicher Weise wird die Sprache auf Chinesisch geschnitten, wenn der Parameter nach der URL auf locale=zh_CH eingestellt ist.
Laden Sie mehrere internationale Dateien direkt aus einem Ordner
Auf unserer Hello.html -Seite gibt es nur zwei internationale Informationen 'i18n_page' und 'Hallo'. In den tatsächlichen Projekten wird es jedoch definitiv nicht so klein wie einige internationale Informationen geben, normalerweise Hunderte von ihnen. Anschließend dürfen wir nicht so viele internationale Informationen in eine Datei mit messages.properties einfügen. Wenn das Projekt jedoch größer wird, werden diese internationalen Dateien immer mehr. Zu diesem Zeitpunkt ist es unpraktisch, diese Datei einzeln in der Datei application.properties zu konfigurieren. Jetzt implementieren wir eine Funktion, um alle internationalen Dateien automatisch im Formulierungsverzeichnis zu laden.
Erben ressourcenBundLemessageSource
Erstellen Sie eine Klasse im Rahmen des Projekts, um ResourceBundleMessageSource oder ReloadableResourceBundleMessageSource zu erben und es MessageResourceExtension zu benennen. Und injizieren Sie es in die Bean und den benannten messageSource , wo wir ResourcebundLemessagesource erben.
@Component ("messageSource") öffentliche Klasse MessageresourceEXTension erweitert ResourcebundLemessageSource {} Beachten Sie, dass unser Komponentenname "MessageSource" sein muss, da bei der Initialisierung ApplicationContext die Bean mit der Bean mit dem Namen "MessageSource" nachgeschlagen wird. Dieser Prozess erfolgt in AbstractApplicationContext.java . Schauen wir uns den Quellcode an
/*** Initialisieren Sie die MessageSource.*Verwenden Sie übergeordnete, wenn keine in diesem Zusammenhang definiert ist.*/Protected void initMessageSource () {configurableListableBeanFactory beanfactory = getBeanFactory (); if (beanfactory.containsLocalBean (message_source_bean_name)) {this.messageSource = beanfactory.getBean (message_source_bean_name, messusource.class); ...}} ... Bei dieser Methode zur Initialisierung von MessageSource sucht Beanfactory nach Beans, die mit dem Namen MESSAGE_SOURCE_BEAN_NAME(messageSource) injiziert werden. Wenn nicht gefunden, wird nach der Frage, ob es eine Bohne mit dem Namen in seiner übergeordneten Klasse gibt.
Dateiladen implementieren
Jetzt können wir MessageResourceExtension starten, die wir gerade erstellt haben
Die Methode zum Laden der Datei ist geschrieben.
@Component ("messageSource") öffentliche Klasse MessageresourceExtesion erweitert ResourcebundLemessageSource {private endgültige statische Logger logger = loggerfactory.getLogger (MessageresourceExtesion.class); / *** spezifiziertes Internationalisierungsdatei -Verzeichnis*/ @Value (value = "$ {Spring.Messages.BaseFolder: i18n}") private String -BasisFolder; / *** Internationalisierungsdatei, angegeben von übergeordnetem Messagesource*/ @Value (value = "$ {spring.messages.basename: message}") private String -Basisname; @Postconstruct public void init () {logger.info ("init MessageresourceEXTension ..."); if (! Stringutils.isempty (BaseFolder)) {try {this.setBasenamen (getAllBasenamen (BaseFolder)); } catch (ioException e) {logger.Error (e.getMessage ()); }} // Setzen Sie übergeordnete MessageSource ResourcebundLemessageSource Eltern = new ResourcebundLemessageSource (); parent.setBasename (BasisName); this.setParentMessageSource (Elternteil); } / ** * Erhalten Sie alle internationalen Dateinamen im Ordner * * @param Ordnername Dateiname * @return * @throws iOException * / private String [] getAllBaseNames (String -Ordnere) löscht IOException {Resource Resource = New ClassSource (Ordnerame) aus; Datei Datei = Resource.getFile (); Liste <String> BasisNames = New ArrayList <> (); if (file.exists () && file.isdirectory ()) {this.getallFile (Basenamen, Datei, ""); } else {logger.Error ("Die angegebene Basisklasse existiert nicht oder ist kein Ordner"); } return baseSenames.toArray (neue String [BasisNames.size ()]); } /** * traverse all files* * @param basenames * @param folder * @param path */ private void getAllFile(List<String> basenames, File folder, String path) { if (folder.isDirectory()) { for (File file : folder.listFiles()) { this.getAllFile(basenames, file, path + folder.getName() + Datei.Sesparator); }} else {string i18name = this.geti18FileName (path + order.getName ()); if (! baseSenames.Contains (i18Name)) {BasisNames.Add (i18Name); }}} / ** * Normale Dateinamen in internationale Dateinamen konvertieren * * @param Dateiname * @return * / private String geti18FileName (String -Dateiname) {FileName = Dateiname.replace ("Eigenschaften", "); für (int i = 0; i <2; i ++) {int index = fileName.lastIndexof ("_"); if (index! = -1) {Dateiname = Dateiname.substring (0, Index); }} return Dateiname; }}Erklären Sie nacheinander mehrere Methoden.
@PostConstruct -Annotation für init() -Methode, mit der init() -Methode automatisch aufgerufen wird, nachdem die MessageresourceEXTensions -Klasse instanziiert ist. Diese Methode erhält alle Internationalisierungsdateien im Verzeichnis baseFolder und setzt sie auf basenameSet . Und setzen Sie eine ParentMessageSource fest, mit der die übergeordnete MessageSource aufgerufen wird, um die internationalen Informationen zu finden, wenn die internationalen Informationen nicht gefunden werden können.getAllBaseNames() erhält den Pfad zum baseFolder und ruft dann getAllFile() auf, um die Dateinamen aller internationalen Dateien im Verzeichnis zu erhalten.getAllFile() durchquert das Verzeichnis, wenn es sich um einen Ordner handelt, fährt weiterhin durch, wenn es sich um eine Datei handelt. Rufen Sie getI18FileName() auf, um den Dateinamen in einen internationalen Ressourcennamen im Format 'i18n/Basename/' zu konvertieren. Einfach einfach ausgedrückt, nachdem MessageResourceExtension instanziiert ist, wird der Name der Ressourcendatei unter dem Ordner 'i18n' in Basenames geladen. Lassen Sie uns nun den Effekt sehen.
Zunächst fügen wir der Datei application.Properties eine spring.messages.baseFolder=i18n hinzu, die baseFolder im MessageResourceExtension den Wert 'i18n' zuweist.
Nach dem Start sah ich, dass die Init -Informationen in der Konsole gedruckt wurden, was darauf hinweist, dass die von @PostConstruct kommentierte Init () -Methode ausgeführt wurde.
Anschließend erstellen wir zwei Sätze internationaler Informationsdateien: 'Dashboard' und 'Merchant', die nur eine internationale Information haben: 'Dashboard.hello' bzw. 'Merchant.hello'.
Ändern Sie dann die Hello.html -Datei und besuchen Sie dann die Hello -Seite.
... <body> <h1> Internationalisierung Seite!
Sie können sehen, dass die Internationalisierungsinformationen in "Nachricht", "Dashboard" und "Händler" auf der Webseite geladen sind, um anzuzeigen, dass wir die Datei erfolgreich unter dem Ordner "i18n" gleichzeitig geladen haben.
Dateien, die internationale Informationen auf der Front-End-Seite der Hintergrundeinstellungen anzeigen
Im vorherigen Abschnitt haben wir mehrere Internationalisierungsdateien erfolgreich geladen und ihre Internationalisierungsinformationen angezeigt. Die Internationalisierungsinformationen in 'Dashboard.Properties' sind jedoch 'Dashboard.hello' und 'Merchant.Properties' 'Merchant.hello'. Es wäre also sehr problematisch, für jeden ein Präfix zu schreiben. Jetzt möchte ich nur noch in den Internationalisierungsdateien von 'Dashboard' und 'Händler' 'Hallo' schreiben, aber die Internationalisierungsinformationen in 'Dashboard' oder 'Händler' werden angezeigt.
Schreiben Sie die Methode resolveCodeWithoutArguments in MessageResourceExtension um (schreiben Sie resolveCode neu, wenn eine Zeichenformatierung erforderlich ist).
@Component ("messageSource") öffentliche Klasse MessageresourceEXTension erweitert ResourcebundLemessageSource {... public static String i18n_attribute = "i18n_attribute"; @Override Protected String String resolvecodeWitHoutArgumente (String -Code, Gebietsgebietsschale) {// den angegebenen internationalen Dateinamen in der Anforderung servletRequestattributes attr = (ServletRequestAttributes) RequestContexTHolder.CurrentRequestAttributes (); endgültige Zeichenfolge i18File = (String) attr.getAttribute (i18n_attribute, RequestAttributes.scope_Request); if (! Stringutils.isempty (i18File)) {// den internationalen Dateinamen in der BasisNameSet -String -Basisname = getBasenAmySet (). if (! Stringutils.isempty (BasisName)) {// Erhalten Sie die angegebene internationale Ressourcenressourcen -Ressourcen -Bündel = getResourcebundle (BasisName, Lokale); if (bündel! = null) {return getStringornull (Bundle, Code); }}} // Wenn es im angegebenen I18 -Ordner kein Internationalisierungsfeld gibt, sucht die Rückgabe von NULL in ParentMessageSource nach Rückgabe -Null. } ...} In der von uns neu geschriebenen resolveCodeWithoutArguments -Methode erhalten Sie "i18n_attribute" von httpServletRequest (werden Sie darüber sprechen, wo Sie dies festlegen können), der dem internationalen Dateinamen entspricht, den wir anzeigen möchten. Dann schauen wir die Datei im BasenameSet nach, erhalten dann die Ressource durch getResourceBundle und schließlich getStringOrNull um die entsprechenden internationalen Informationen zu erhalten.
Fügen wir jetzt zwei Methoden zu unserem HelloController hinzu.
@ControllerPublic Class HelloConTroller {@getmapping ("/hello") public String Index (httpServletRequest -Anforderung) {Request.SetAttribute (MessageresourceExtesion.i18n_attribute, "Hallo"); Rückgabe "System/Hallo"; } @Getmapping ("/Dashboard") public String Dashboard (httpServletRequest -Anforderung) {Request.SetAttribute (MessageresourceExtesion.i18n_attribute, "Dashboard"); Rückgabe "Dashboard"; } @Getmapping ("/merchant") public String Merchant (httpServletRequest Request) {Request.SetAttribute (MessageresourceExtesion.i18n_attribute, "Merchant"); zurück "Merchant"; }} Sehen Sie, dass wir in jeder Methode eine entsprechende "i18n_attribute" einstellen, die die entsprechende Internationalisierungsdatei in jeder Anforderung festlegt und sie dann in MessageResourceExtension erhalten.
Zu diesem Zeitpunkt schauen wir uns unsere Internationalisierungsdatei an und können sehen, dass alle Schlüsselwörter "Hallo" sind, aber die Informationen sind unterschiedlich.
Gleichzeitig sind zwei neue HTML -Dateien "Dashboard.html" und "Merchant.html", die nur internationale Informationen für "Hallo" und einen Titel zum Unterscheiden enthält.
<!-Dies ist Hallo.html-> <body> <h1> Internationalisierung Seite!
<!-Dies ist Dashboard.html-> <body> <h1> Internationalisierung (Dashboard)!
<!-Dies ist Merchant.html-> <body> <h1> Internationalisierung (Händler)!
Lassen Sie uns zu diesem Zeitpunkt das Projekt starten und einen Blick darauf werfen.
Sie können sehen, dass das Internationalisierungswort auf jeder Seite jedoch "Hallo" ist, die Informationen, die wir auf der entsprechenden Seite anzeigen möchten, angezeigt werden.
Verwenden Sie Interceptors und Anmerkungen, um Dateien automatisch einzurichten, die internationale Informationen auf der Front-End-Seite anzeigen
Obwohl die entsprechenden Internationalisierungsinformationen angegeben werden können, ist es zu problematisch, die Internationalisierungsdatei in der httpServletRequest in jedem Controller festzulegen. Daher implementieren wir nun ein automatisches Urteil, um die entsprechende Datei anzuzeigen.
Zuerst erstellen wir eine Annotation, die auf eine Klasse oder eine Methode platziert werden kann.
@Target ({elementtype.type, elementtype.method}) @retention (retentionpolicy.runtime) public @Interface i18n { / *** Internationalisierter Dateiname* / string value ();};};};}; Dann setzen wir die I18n -Annotation, die gerade in der Controller -Methode erstellt wurde. Um seinen Effekt anzuzeigen, erstellen wir einen ShopController und UserController und erstellen auch die entsprechenden "Shop" und "Benutzer" internationale Dateien, und der Inhalt ist auch ein "Hallo".
@ControllerPublic Class HelloConTroller {@getMapPing ("/hello") public String index () {return "System/Hallo"; } @I18n ("Dashboard") @getMapping ("/Dashboard") public String Dashboard () {return "Dashboard"; } @I18n ("Merchant") @getMapping ("/Merchant") public String merchant () {return "Merchant"; }} @I18n ("Shop") @ControllerPublic Class ShopController {@getMapping ("Shop") public String Shop () {return "Shop"; }} @ControllerPublic Class UserController {@getMapping ("user") public String user () {return "user"; }} Wir legen I18n -Annotation unter dashboard und merchant unter HelloController bzw. in ShopController -Klasse. Und die Anweisung, die 'i18n_attribute' unter das ursprüngliche dashboard und merchant festgelegt wird.
Die Vorbereitungen sind alle erledigt. Sehen Sie nun, wie die Internationalisierungsdateien automatisch auf diesen Anmerkungen angeben.
öffentliche Klasse MessageresourceInterceptor implementiert HandlerInterceptor {@Override public void posthandle (httpServletRequest req, httpServletResponse Rep, Object Handler, modelAndView modelAndView) {// setze den i18 -Path in der Methode (null! } HandleMethod -Methode = (HandleMethod) Handler; // Annotation zur Methode I18 I18N I18NMethod = method.getMethodannotation (i18n.class); if (null! zurückkehren; } // Annotation auf dem Controller i18n i18ncontroller = method.getBeanType (). getAnnotation (i18n.class); if (null! zurückkehren; } // I18 String controller = methode.getBeANType (). GetName (); int index = controller.lastIndexof ("."); if (index! } index = Controller.ToUpperCase (). IndexOf ("Controller"); if (index! } index = Controller.ToUpperCase (). IndexOf ("Controller"); if (index! } req.setAttribute (MessageresourceExtesion.i18n_attribute, Controller); } @Override public boolean prehandle (httpServletRequest req, httpServletResponse -Rep, Objekthandler) {// Wenn Sie zu dieser Methode springen, löschen Sie zunächst die Internationalisierungsinformationen in der Anforderung req.removeAttribute (MessageSourceEXtsion.i18n_atTribute); zurückkehren; }}Lassen Sie mich diesen Interceptor kurz erklären.
Erstens, wenn in der Anfrage bereits 'i18n_attribute' enthalten ist, bedeutet dies, dass die Einstellungen in der Controller -Methode angegeben sind und kein Beurteilungsurteil vorgenommen wird.
Stellen Sie dann fest, ob die Methode zur Eingabe des Interceptors eine I18n -Annotation gibt. Wenn ja, setzen Sie "i18n_attribute" in die Anfrage und beenden Sie den Interceptor. Wenn es nein gibt, fahren Sie fort.
Stellen Sie dann fest, ob es in der Klasse eine I18n -Annotation gibt, die in den Abfang eingegeben wurde. Wenn ja, setzen Sie "i18n_attribute" in die Anfrage und beenden Sie den Interceptor. Wenn es nein gibt, fahren Sie fort.
Wenn die Methode und Klasse keine I18n -Annotation vorhanden ist, können wir die angegebene Internationalisierungsdatei automatisch gemäß dem Controller -Namen festlegen. Zum Beispiel "UserController" suchen wir nach der Internationalisierungsdatei "Benutzer".
Führen wir nun erneut den Effekt aus und sehen den Inhalt in ihren entsprechenden internationalen Informationen, die auf jedem Link angezeigt werden, sehen.
endlich
Ich habe gerade die grundlegenden Funktionen unserer gesamten Internationalisierungsverstärkung abgeschlossen. Schließlich habe ich den gesamten Code und den integrierten Bootstrap4 aussortiert, um den Implementierungseffekt der Funktion anzuzeigen.
Für einen detaillierten Code finden Sie im Code von Spring-Boot-I18N-Pro unter GitHub
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, es wird für das Lernen aller hilfreich sein und ich hoffe, jeder wird Wulin.com mehr unterstützen.