Локали как часть URL в Spring MVC

Я теперь ищу платформу для многоязычных веб-приложений. В данный момент мне кажется, что лучшим выбором является Spring MVC. Но я считался с фактом, что все инструкции для разработчиков предлагают переключить использование языков LocaleChangeInterceptor таким способом:

http://www.somesite.com/action/?locale=en

К сожалению, существует много причин, почему я хотел бы, избегают этого. Как я мог сделать код языка, чтобы быть основной частью URL? Например:

http://www.somesite.com/en/action

Спасибо.

UPD: я нашел следующее решение. Это еще не завершено, но работы. Решение состоит в двух частях - фильтр сервлета и боб сопоставителя локали. Это - взгляды немного hackish, но я не вижу другой способ решить эту проблему.

public class LocaleFilter implements Filter
{

    ...

    private static final String DEFAULT_LOCALE = "en";
    private static final String[] AVAILABLE_LOCALES = new String[] {"en", "ru"};

    public LocaleFilter() {} 

    private List getSevletRequestParts(ServletRequest request)
    {
        String[] splitedParts = ((HttpServletRequest) request).getServletPath().split("/");
        List result = new ArrayList();

        for (String sp : splitedParts)
        {
            if (sp.trim().length() > 0)
                result.add(sp);
        }

        return result;
    }

    private Locale getLocaleFromRequestParts(List parts)
    {
        if (parts.size() > 0)
        {
            for (String lang : AVAILABLE_LOCALES)
            {
                if (lang.equals(parts.get(0)))
                {
                    return new Locale(lang);
                }
            }
        }

        return null;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException
    {
        List requestParts = this.getSevletRequestParts(request);
        Locale locale = this.getLocaleFromRequestParts(requestParts);

        if (locale != null)
        {
            request.setAttribute(LocaleFilter.class.getName() + ".LOCALE", locale);

            StringBuilder sb = new StringBuilder();
            for (int i = 1; i < requestParts.size(); i++)
            {
                sb.append('/');
                sb.append((String) requestParts.get(i));
            }

            RequestDispatcher dispatcher = request.getRequestDispatcher(sb.toString());
            dispatcher.forward(request, response);
        }
        else
        {
            request.setAttribute(LocaleFilter.class.getName() + ".LOCALE", new Locale(DEFAULT_LOCALE));
            chain.doFilter(request, response);
        }
    }

    ...
}

public class FilterLocaleResolver implements LocaleResolver
{

    private Locale DEFAULT_LOCALE = new Locale("en");

    @Override
    public Locale resolveLocale(HttpServletRequest request)
    {
        Locale locale = (Locale) request.getAttribute(LocaleFilter.class.getName() + ".LOCALE");
        return (locale != null ? locale : DEFAULT_LOCALE);
    }

    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale)
    {
        request.setAttribute(LocaleFilter.class.getName() + ".LOCALE", locale);
    }

}

Таким образом, нет никакой потребности отобразить локаль в каждом действии в контроллерах. Следующий пример будет хорошо работать:

@Controller
@RequestMapping("/test")
public class TestController
{

    @RequestMapping("action")
    public ModelAndView action(HttpServletRequest request, HttpServletResponse response)
    {
        ModelAndView mav = new ModelAndView("test/action");
        ...
        return mav;
    }

}

15
задан Gris 11 July 2010 в 17:41
поделиться