Spring Webflux國際化

banq發表於2019-01-17

這篇技術文章中,我們將看到如何在Spring Webflux應用程式中使用不同語言以及Thymeleaf模板框架。

讓我們使用這個命令建立一個新專案:

spring init --dependencies=webflux --build=gradle --language=java spring-webflux-internationalization


這是生成的build.gradle檔案:

buildscript {
  ext {
    springBootVersion = '2.1.2.RELEASE'
  }
  repositories {
    mavenCentral()
  }
  dependencies {
    classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
  }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'

group = 'com.jos.dem.spring.webflux.internationalization'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
    mavenCentral()
}

dependencies {
  implementation('org.springframework.boot:spring-boot-starter-webflux')
  testImplementation('org.springframework.boot:spring-boot-starter-test')
  testImplementation('io.projectreactor:reactor-test')
}


然後將Thymeleaf依賴項新增到您的build.gradle檔案中:

implementation('org.thymeleaf:thymeleaf-spring5:3.0.11.RELEASE')

Spring Boot有一個用於解析訊息的策略介面,支援此類訊息的國際化。

@Bean
public MessageSource messageSource() {
  ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
  messageSource.setBasenames("i18n/messages");
  messageSource.setDefaultEncoding("UTF-8");
  return messageSource;
}


現在是配置模板解析器,模板引擎和檢視解析器的時候了,因為我們需要將Thymeleaf配置為html模板。

@Bean
public ITemplateResolver thymeleafTemplateResolver() {
  final SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
  resolver.setApplicationContext(this.context);
  resolver.setPrefix("classpath:templates/");
  resolver.setSuffix(".html");
  resolver.setTemplateMode(TemplateMode.HTML);
  resolver.setCacheable(false);
  resolver.setCheckExistence(false);
  return resolver;
}

@Bean
public ISpringWebFluxTemplateEngine thymeleafTemplateEngine() {
  SpringWebFluxTemplateEngine templateEngine = new SpringWebFluxTemplateEngine();
  templateEngine.setTemplateResolver(thymeleafTemplateResolver());
  return templateEngine;
}

@Bean
public ThymeleafReactiveViewResolver thymeleafReactiveViewResolver() {
  ThymeleafReactiveViewResolver viewResolver = new ThymeleafReactiveViewResolver();
  viewResolver.setTemplateEngine(thymeleafTemplateEngine());
  return viewResolver;
}

@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
  registry.viewResolver(thymeleafReactiveViewResolver());
}


這是完整的完整Web配置:


@Configuration
@EnableWebFlux
public class WebConfig implements ApplicationContextAware, WebFluxConfigurer {

  private ApplicationContext context;

  @Override
  public void setApplicationContext(ApplicationContext context) {
    this.context = context;
  }

  @Bean
  public MessageSource messageSource() {
    ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
    messageSource.setBasenames("i18n/messages");
    messageSource.setDefaultEncoding("UTF-8");
    return messageSource;
  }

  @Bean
  public ITemplateResolver thymeleafTemplateResolver() {
    final SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
    resolver.setApplicationContext(this.context);
    resolver.setPrefix("classpath:templates/");
    resolver.setSuffix(".html");
    resolver.setTemplateMode(TemplateMode.HTML);
    resolver.setCacheable(false);
    resolver.setCheckExistence(false);
    return resolver;
  }

  @Bean
  public ISpringWebFluxTemplateEngine thymeleafTemplateEngine() {
    SpringWebFluxTemplateEngine templateEngine = new SpringWebFluxTemplateEngine();
    templateEngine.setTemplateResolver(thymeleafTemplateResolver());
    return templateEngine;
  }

  @Bean
  public ThymeleafReactiveViewResolver thymeleafReactiveViewResolver() {
    ThymeleafReactiveViewResolver viewResolver = new ThymeleafReactiveViewResolver();
    viewResolver.setTemplateEngine(thymeleafTemplateEngine());
    return viewResolver;
  }

  @Override
  public void configureViewResolvers(ViewResolverRegistry registry) {
    registry.viewResolver(thymeleafReactiveViewResolver());
  }

}


如您所見SpringResourceTemplateResolver,負責設定我們的模板檔案路徑和副檔名。在這種情況下,將定義一個index.html帶有hello world訊息的網頁。

<html>
  <head>
    <meta charset="utf-8">
    <title>Internationalization with Spring Webflux</title>
  </head>
  <body></body>
</html>


ResourceBundleMessageSource為每種支援的語言定義訊息資源路徑。在這種情況下,我們將定義messages.properties為英語。

user.hello=Hello from internationalization!

messages_es.properties為西班牙:

user.hello=¡Hola Internacionalización!

下一步是告訴Spring使用Locale解析器。所以我們需要新增一個擴充套件自DelegatingWebFluxConfiguration定義的配置類LocaleContextResolver。

@Configuration
public class LocaleSupportConfig extends DelegatingWebFluxConfiguration {

  @Override
  protected LocaleContextResolver createLocaleContextResolver() {
    return new LocaleResolver();
  }

}

這是我們的語言環境解析器:

public class LocaleResolver implements LocaleContextResolver {

  @Override
  public LocaleContext resolveLocaleContext(ServerWebExchange exchange) {
    String language = exchange.getRequest().getHeaders().getFirst("Accept-Language");

    Locale targetLocale = Locale.getDefault();
    if (language != null && !language.isEmpty()) {
      targetLocale = Locale.forLanguageTag(language);
    }
    return new SimpleLocaleContext(targetLocale);
  }

  @Override
  public void setLocaleContext(ServerWebExchange exchange, LocaleContext localeContext) {
    throw new UnsupportedOperationException("Not Supported");
  }

}


就是這樣,我們在客戶請求的標題中閱讀語言支援,這樣我們就可以向客戶顯示正確的訊息,無論是使用英語還是西班牙語。最後,這是我們的控制器來呈現索引網頁。

@Controller
public class InternationalizationController {

  @GetMapping("/")
  public String index() {
    return "index";
  }

}

要執行專案:

gradle bootRun


請到此處下載專案。

相關文章