Как получить 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());
// ...
BalusC
источник
Есть ли причина использовать это вместо 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())
fforw
источник
Потрясающие! Это именно то, что я искал.
мастер
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());
    ...

}
lukastymo
источник
8

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

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

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

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

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

thetoolman
источник
5

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

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

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

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

PeterMmm
источник
-1

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

string[] uris=request.getRequestURI().split("/");
string uri="/"+uri[1]+"/"+uris[2];
Colin
источник
3
Это вызовет проблему, если я разверну свое приложение как root, а его базовый URL станет localhost: 8080 . В этом случае request.getRequestURI () вернет "/ secure / user", и ваш метод разделения вызовет здесь проблему. Код не должен зависеть от развертывания.
ремесленник