如何使用nginx后面的多个域的单个tomcat实例用于i18n

时间:2016-05-30 10:28:32

标签: spring-mvc tomcat nginx configuration internationalization

我在nginx代理服务器后面的tomcat(8080)上有一个Spring MVC应用程序。我还有3个不同的域名:

  1. www.mywebsite.com for English
  2. www.mywebsite.de for German
  3. www.mywebsite.fr for French
  4. 现在我必须确保当用户访问 www.mywebsite.de 时,网站的语言必须是德语,*。com应该是英语等等。

    那么如何使用单个tomcat实例实现

    我可以启动三个tomcat实例:

    1. localhost:8080,默认语言环境为“DE”
    2. localhost:8081,默认语言环境为“EN”
    3. localhost:8082,默认语言环境为“RU”
    4. 然后在我的ngnix配置中,我会以这种方式通过proxy_pass转发所有请求:

      1. domain.de - >本地主机:8080
      2. domain.com - >本地主机:8081
      3. domain.ru - >本地主机:8082
      4. 这意味着我必须维护3个tomcat实例。这就是为什么这个问题。

3 个答案:

答案 0 :(得分:2)

  
    

tomcat下的应用程序需要知道它需要服务的语言。你是怎么做到的? - Sangram Jadhav 6月6日7:12

  
     

@SangramJadhav over Locale和?lang=en - dit Jun 7 at 18:21

那么,您可以使用nginx在将请求代理到tomcat中的应用程序之前修改请求,以添加额外的?lang=XX,具体取决于'被访问。

map directive可能最适合在域和语言之间进行映射:

map $http_host $lang {
  hostnames;

  default       en;

  example.de    de;
  *.example.de  de;
  example.at    de;
  *.example.at  de;
  example.fr    fr;
  *.example.fr  fr;
  example.cd    fr;
  *.example.cd  fr;
  example.ru    ru;
  *.example.ru  ru;
  example.by    ru;
  *.example.by  ru;
}

随后,您只需将此添加到proxy_pass directive$uri$args处理的每个请求中:

proxy_pass http://127.0.0.1:8080$uri?$args&lang=$lang;

但请注意,使用proxy_pass中的变量会将off proxy_redirect feature从其默认值default变为proxy_redirect http://127.0.0.1:8080/ /; ,因此,您可能还需要添加类似这样的内容到你的配置:

Crop.pickImage(CurrentActivity.this, IMAGE_CHOOSER_REQUEST_COODE);

此外,如果您使用proxy_cache,则可能需要修改proxy_cache_key

答案 1 :(得分:1)

设置spring mvc的语言环境应该与servlet容器(tomcat)或代理(nginx)无关。春天就是managing这一切。

查看此示例http://www.mkyong.com/spring-mvc/spring-mvc-internationalization-example/

您不希望在服务器级别拥有这样的应用程序逻辑的一个原因是它会使扩展更加困难。无论您需要为TLD创建一个映射文件到Locale。对于每个映射,您需要一个语言文件。当您添加其他区域设置时,只需重新部署单个应用程序与代理和应用程序即可。

如果您将TLD映射到服务器,则必须为每种语言创建缩放组。然后你可能最终得到一堆节点闲置,什么都不做,同时有一堆负载服务单一语言。如果你在像AWS这样的东西上运行,你将会获得更高的月度账单。

它还使本地开发和部署都很复杂。当你只有一个应用程序时,生活会好得多。如果您支持10种语言,则必须进行10次部署,因为每个应用程序都需要不同的参数来开始设置默认语言环境。

如果您想基于域TLD制作语言环境,可以扩展SessionLocaleResolver。见source

在我正在使用的应用中,我使用的是Spring的CookieLocaleResolver

@Bean
public LocaleResolver localeResolver() {
    CookieLocaleResolver resolver = new CookieLocaleResolver();
    resolver.setDefaultLocale(Locale.ENGLISH);
    return resolver;
}

您只需要执行LocaleResolver。您可以从HttpServletRequest获取TLD。然后,只需根据您的规则返回正确的区域设置即可。

答案 2 :(得分:0)

好的是,目前的解决方案是覆盖您的LocaleResolver。这不是我的最爱,因为如果我添加新TLD,我每次都必须扩展代码。但无论如何,这是一个例子:

public class CustomCookieLocaleResolver extends CookieLocaleResolver {

    private static final Locale      LOCALE_RU      = new Locale("ru");
    private static final Set<String> UNDERSTAND_RU  = new HashSet<>(Arrays.asList("ru", "be", "kz", "uk"));

    @Override
    protected Locale determineDefaultLocale(HttpServletRequest request) {

        Locale locale = getLangByHostName(request);

        if (locale == null) {

            // Header: Accept-Language or server default locale
            String lang = request.getLocale().getLanguage();

            if (Locale.GERMAN.getLanguage().equals(lang)) {
                return Locale.GERMAN;
            } else if (UNDERSTAND_RU.contains(lang)) {
                return LOCALE_RU;
            }
        }

        return Locale.ENGLISH;
    }

    private Locale getLangByHostName(HttpServletRequest request) {

        String host = request.getServerName();

        if (host.endsWith(".de")) return Locale.GERMAN;
        if (host.endsWith(".ru")) return LOCALE_RU;

        return null;
    }

}

我相信在nginx /代理级别上也可以覆盖依赖于TLD的Accept-Language头。