Какой лучший способ получить текущий URL-адрес в Spring MVC?

95

Я хочу создать URL-адреса на основе URL-адреса, используемого клиентом для активного запроса. Есть ли что-нибудь умнее, чем взять текущий HttpServletRequestобъект и его getParameter...()методы для восстановления полного URL-адреса, включая (и только) его параметры GET.

Уточнение: Если возможно, я хочу отказаться от использования HttpServletRequestобъекта.

Корактор
источник

Ответы:

111

Что ж, есть два метода для более простого доступа к этим данным, но интерфейс не предлагает возможности получить весь URL-адрес за один вызов. Придется собрать вручную:

public static String makeUrl(HttpServletRequest request)
{
    return request.getRequestURL().toString() + "?" + request.getQueryString();
}

Я не знаю, как это сделать с помощью каких-либо средств Spring MVC.

Если вы хотите получить доступ к текущему запросу, не передавая его повсюду, вам нужно будет добавить слушателя в web.xml:

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

А затем используйте это, чтобы привязать запрос к текущему потоку:

((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()
Дафф
источник
Хорошо, это аналогичный подход к тому, что я делал до сих пор. Но я ищу способ сделать это, фактически не используя HttpServletRequestобъект. Это потому, что я использую несколько вспомогательных классов / методов и не хочу каждый раз передавать объект запроса.
Koraktor
Хорошо, я знаю, что вы имеете в виду, и добавил информацию, необходимую для доступа к текущему запросу, не передавая его.
Daff
Спасибо за напоминание о слушателе. Я все еще новичок в Spring (и в веб-разработке на Java в целом). Теперь я использую ваш код в сочетании с Spring Security UrlUtils. Работает как шарм.
Koraktor
В моем случае он дает связанный путь просмотра вместо URL-адреса просмотра. Есть идеи по этому поводу?
Md. Shougat Hossain 05
76

Вместо RequestContextHolderпрямого использования вы также можете использовать ServletUriComponentsBuilderи его статические методы:

  • ServletUriComponentsBuilder.fromCurrentContextPath()
  • ServletUriComponentsBuilder.fromCurrentServletMapping()
  • ServletUriComponentsBuilder.fromCurrentRequestUri()
  • ServletUriComponentsBuilder.fromCurrentRequest()

Они используют RequestContextHolderвнутренние ресурсы, но обеспечивают дополнительную гибкость для создания новых URL-адресов с использованием возможностей UriComponentsBuilder.

Пример:

ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromCurrentRequestUri();
builder.scheme("https");
builder.replaceQueryParam("someBoolean", false);
URI newUri = builder.build().toUri();
Корактор
источник
@ m4rtin Я ответил на свой вопрос и не хотел отдавать должное тому, кто изначально помог мне решить мою проблему.
Koraktor 08
2
Также хорошо для Spring 5. Мне удалось получить URL-адрес внутри файла ConstraintValidatorwith ServletUriComponentsBuilder.fromCurrentRequestUri().toUriString();.
GuiRitter 05
16

В этом вам может помочь класс URI Java:

public static String getCurrentUrl(HttpServletRequest request){
    URL url = new URL(request.getRequestURL().toString());
    String host  = url.getHost();
    String userInfo = url.getUserInfo();
    String scheme = url.getProtocol();
    String port = url.getPort();
    String path = request.getAttribute("javax.servlet.forward.request_uri");
    String query = request.getAttribute("javax.servlet.forward.query_string");

    URI uri = new URI(scheme,userInfo,host,port,path,query,null)
    return uri.toString();
}
Рид Грей
источник
он дает только имя хоста
vivex 05
8

в файле jsp:

request.getAttribute("javax.servlet.forward.request_uri")
Энди
источник
3

Вы также можете добавить UriComponentsBuilderк сигнатуре метода вашего метода контроллера. Spring внедрит экземпляр построителя, созданного из текущего запроса.

@GetMapping
public ResponseEntity<MyResponse> doSomething(UriComponentsBuilder uriComponentsBuilder) {
    URI someNewUriBasedOnCurrentRequest = uriComponentsBuilder
            .replacePath(null)
            .replaceQuery(null)
            .pathSegment("some", "new", "path")
            .build().toUri();
  //...
}

Используя конструктор, вы можете напрямую начать создание URI на основе текущего запроса, например, изменить сегменты пути.

См. Также UriComponentsBuilderMethodArgumentResolver

Матиас Дпункт
источник
Обратите внимание, что введенный UriComponentsBuilderне включает путь и параметры запроса запроса. Если вам нужно получить доступ к ним, используйте ServletUriComponentsBuilder.fromCurrentRequest()или внедрите экземпляр HttpServletRequestи используйтеServletUriComponentsBuilder.fromRequest(request)
Мартин Девиллерс
-1

Если вам нужен URL-адрес до имени хоста, а не путь, используйте Apache Common Lib StringUtil, а из URL-адреса извлеките подстроку до третьего indexOf /.

public static String getURL(HttpServletRequest request){
   String fullURL = request.getRequestURL().toString();
   return fullURL.substring(0,StringUtils.ordinalIndexOf(fullURL, "/", 3)); 
}

Пример: если fullURL равен, https://example.com/path/after/url/то вывод будет https://example.com

Сахил Чабра
источник