Как получить URI запроса без контекстного пути?


127

Метод request.getRequestURI () возвращает URI с контекстным путем.

Например, если базовый URL из приложения http://localhost:8080/myapp/(то есть контекст путь MyApp ), и я призываю request.getRequestURI()к http://localhost:8080/myapp/secure/users, он вернется /myapp/secure/users.

Есть ли способ получить только эту часть /secure/users, то есть URI без контекстного пути?


Ответы:


158

Если вы находитесь внутри сервлета переднего контроллера, который отображается в шаблоне префикса, вы можете просто использовать HttpServletRequest#getPathInfo().

String pathInfo = request.getPathInfo();
// ...

Предполагая, что сервлет в вашем примере сопоставлен /secure, тогда будет возвращена /usersинформация, представляющая единственный интерес внутри типичного сервлета фронт-контроллера.

Однако, если сервлет сопоставлен с шаблоном суффикса (ваши примеры URL, однако, не указывают, что это так) или когда вы на самом деле находитесь внутри фильтра (когда сервлет, который должен быть запущен, еще не обязательно определен, поэтому getPathInfo()может вернуться null), то лучше всего самостоятельно подставить URI запроса на основе длины контекстного пути, используя обычный Stringметод:

HttpServletRequest request = (HttpServletRequest) req;
String path = request.getRequestURI().substring(request.getContextPath().length());
// ...

Есть ли причина использовать это вместо getServletPath()? Я пишу фильтр и заметил, что он getPathInfo()возвращается null, но getServletPath()возвращает путь без контекста (подходит для передачи диспетчеру запросов).
Jason C

@JasonC: Как уже было сказано, getPathInfo()возвращает null, если сервлет переднего контроллера не сопоставлен с шаблоном префикса.
BalusC

Да. Я имел в виду: есть ли причина, по которой вы предпочитаете getPathInfo, а не getServletPath? Многие другие высоко оцененные ответы здесь также не используют getServletPath, что вызывает у меня подозрение и почему мне интересно. У меня есть проект сервлета, над которым я работаю, и я пытаюсь отточить свои навыки.
Jason C

1
@JasonC: путь сервлета может быть изменен, если у вас установлена ​​среда MVC на основе сервлетов, такая как JSF или Spring MVC. Затем он будет представлять внутренний путь инфраструктуры MVC (например, /foo.xhtmlвместо /foo.jsf), а не фактический URI запроса (тот, который конечный пользователь увидит в адресной строке браузера). Однако исходный путь сервлета в таком случае разрешается как атрибут запроса с ключом RequestDispatcher.FORWARD_SERVLET_PATH. В любом случае вопрос явно запрашивает URI запроса (как в адресной строке браузера), поэтому ответ основан на этом.
BalusC

74
request.getRequestURI().substring(request.getContextPath().length())

Потрясающие! Это именно то, что я искал.
мастер

4
+1 Я думаю, что это лучший ответ, чем getPathInfo из-за того, что getPathInfo может быть нулевым и других странностей. Различный код Spring делает getContextPath и удаляет его из URI так же, как вы это делали вместо getPathInfo.
Адам Гент,

32

С Spring вы можете:

String path = new UrlPathHelper().getPathWithinApplication(request);

1
Конечно, имеет смысл сохранить экземпляр UrlPathHelper, например, в качестве переменной-члена класса ...
Джеймс

Как мы можем получить фактический URL-адрес сопоставления запросов? Пожалуйста, обратитесь сюда: stackoverflow.com/questions/60446807/…
Pra_A

14

getPathInfo () иногда возвращает значение null. В документации HttpServletRequest

Этот метод возвращает значение null, если не было дополнительной информации о пути.

Мне нужно получить путь к файлу без пути контекста в фильтре, а getPathInfo () вернет мне значение null. Поэтому я использую другой метод: httpRequest.getServletPath ()

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;

    String newPath = parsePathToFile(httpRequest.getServletPath());
    ...

}

8

Если вы используете request.getPathInfo () внутри фильтра, вам всегда кажется, что вы получаете null (по крайней мере, с причалом).

Этот краткий недействительный ответ с ошибкой + намекает на проблему, которую я думаю:

https://issues.apache.org/bugzilla/show_bug.cgi?id=28323

Я подозреваю, что это связано с тем, что фильтры запускаются до того, как сервлет получит запрос. Это может быть ошибка контейнера или ожидаемое поведение, которое я не смог определить.

Однако contextPath доступен, поэтому решение fforws работает даже в фильтрах. Мне не нравится делать это вручную, но реализация не работает или


5

Один из способов сделать это - оставить путь контекста сервлета из URI запроса.

String p = request.getRequestURI();
String cp = getServletContext().getContextPath();

if (p.startsWith(cp)) {
  String.err.println(p.substring(cp.length());
}

Прочтите здесь .


-1

Возможно, вы можете просто использовать метод разделения, чтобы удалить '/ myapp', например:

string[] uris=request.getRequestURI().split("/");
string uri="/"+uri[1]+"/"+uris[2];

3
Это вызовет проблему, если я разверну свое приложение как root, а его базовый URL станет localhost: 8080 . В этом случае request.getRequestURI () вернет "/ secure / user", и ваш метод разделения вызовет здесь проблему. Код не должен зависеть от развертывания.
ремесленник
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.