Переопределить getContextPath в HttpServletRequest (для перезаписи URL)

У меня есть веб-приложение, которое я хотел бы расширить для поддержки нескольких языков с новыми URL-адресами. Например, www.example.com/home.do остается английским, а www.example.com/es/home.do — испанским. Моей первой мыслью было создать фильтр, который переписывает входящие URL-адреса, такие как /es/home.do, в /home.do (и устанавливает локаль в запросе); это работает нормально. Фильтр оборачивает ServletRequest с помощью HttpServletRequestWrapper, который переопределяет getContextPath() для возврата языка:

class FakeContextRequest extends HttpServletRequestWrapper {

  private String context = "";
  FakeContextRequest(HttpServletRequest request, String context) {
    super(request);
    // snip some validation code
    this.context = request.getContextPath() + context;
  }
  @Override
  public String getContextPath() {
    return this.context;
  }
}

Мой фильтр перенаправляет соответствующий запрос следующим образом:

FakeContextRequest fr = new FakeContextRequest(request, lang);
fr.getRequestDispatcher(newResourceName).forward(fr, response);

Моя проблема в том, что следующий сервлет не пересылается должным образом. Следующий сервлет (обычно Struts ActionServlet) перенаправляется на JSP (часто с использованием Struts Tiles); когда я добираюсь до JSP, HttpServletRequest был обернут несколько раз, и рассматриваемый объект сообщает, что контекст пуст (корневой контекст, где фактически развернуто приложение).

Я хочу, чтобы контекст был переписан, чтобы весь мой контекстно-зависимый код, который уже существует, мог автоматически вставлять язык в написанные URL-адреса. Это возможно?

Изменить: я решил свою проблему, используя обернутый HttpServletResponse вместо обернутого HttpServletRequest; Я переписываю URL-адрес в методе response.encodeURL().


person Mr. Shiny and New 安宇    schedule 03.11.2008    source источник


Ответы (3)


Я не уверен, что переопределения getContextPath() достаточно для решения вашей проблемы. Что, если Struts вызывает ServletContext.getContextPath() под прикрытием или использует getRequestURI() и т. д.?

person matt b    schedule 03.11.2008

Насколько я знаю, обычный способ сделать это — использовать HTTP-заголовок accept-language. Язык представления — это деталь представления, которая не должна быть представлена ​​набором URL-адресов для навигации по приложению.

person David M. Karr    schedule 03.11.2008
comment
Заголовок accept-language не будет работать, потому что он не совместим с поисковыми системами. Поисковым системам нужны уникальные ссылки, чтобы сканировать контент на разных языках. - person Mr. Shiny and New 安宇; 04.11.2008

Я решил свою проблему, выполнив перезапись URL в response.encodeURL() и друзьях. Объект запроса упаковывается и заменяется по всей цепочке запросов, но объект ответа, похоже, проходит беспрепятственно. Это работает очень надежно.

person Mr. Shiny and New 安宇    schedule 13.11.2008
comment
Я думаю, что этот метод используется в проекте UrlRewriterFilter tuckey.org/urlrewrite. - person Brian Clozel; 14.01.2010