在Spring MVC中获取当前URL的最佳方法是什么?


95

我想基于客户端用于活动请求的URL创建URL。还有什么比采用当前HttpServletRequest对象更聪明的getParameter...()方法吗?它是重建完整URL 的方法,包括(仅)GET参数。

澄清:如果可能的话,我想退出使用一个HttpServletRequest对象。

Answers:


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 Web开发)不熟悉。我现在将您的代码与Spring Security的结合使用UrlUtils。奇迹般有效。
Koraktor

就我而言,它提供了相关的视图路径,而不是浏览URL。有什么想法吗?
Shougat Hossain博士

76

除了RequestContextHolder直接使用之外,还可以使用ServletUriComponentsBuilder及其静态方法:

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

它们RequestContextHolder在幕后使用,但使用以下功能提供了额外的灵活性来构建新的URLUriComponentsBuilder

例:

ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromCurrentRequestUri();
builder.scheme("https");
builder.replaceQueryParam("someBoolean", false);
URI newUri = builder.build().toUri();

@ m4rtin我回答了我自己的问题,不想为最初帮助我解决问题的那个人表示赞赏。
Koraktor

2
对于Spring 5也是很好的。我已经设法在URL中使用ConstraintValidatorwith ServletUriComponentsBuilder.fromCurrentRequestUri().toUriString();
GuiRitter

16

Java的URI类可以帮助您:

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

8

在jsp文件中:

request.getAttribute("javax.servlet.forward.request_uri")

3

您还可以将a添加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)
Martin Devillers 19/12/19

-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)); 
}

示例:如果为fullURLhttps://example.com/path/after/url/输出https://example.com

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.