【问题标题】:What's the best way to get the current URL in Spring MVC?在 Spring MVC 中获取当前 URL 的最佳方法是什么?
【发布时间】:2010-12-02 05:26:35
【问题描述】:

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

澄清:如果可能,我想放弃使用HttpServletRequest 对象。

【问题讨论】:

    标签: url spring-mvc httprequest


    【解决方案1】:

    嗯,有两种方法可以更轻松地访问这些数据,但该界面不提供一次调用获取整个 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 对象的方法。这是因为我使用了几个辅助类/方法,我不想每次都传递请求对象。
    • 好的,我知道你的意思,并添加了访问当前请求所需的信息,而无需传递它。
    • 感谢听众的提醒。我对 Spring(以及一般的 Java Web 开发)仍然很陌生。我现在将您的代码与 Spring Security 的UrlUtils 结合使用。像魅力一样工作。
    • 在我的例子中,它给出了相关的视图路径而不是浏览 url。对此有任何想法吗?
    • 不使用 HttpServletRequest... Spring Boot 控制器方法中的示例,我们没有将其作为参数...然后静态调用的另一个答案看起来不错 ServletUriComponentsBuilder.fromCurrentRequest().toUriString( )
    【解决方案2】:

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

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

    它们在底层使用RequestContextHolder,但提供了额外的灵活性来使用UriComponentsBuilder 的功能构建新的URL。

    例子:

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

    【讨论】:

    • @m4rtin 我回答了我自己的问题,不想把最初帮助我解决问题的人归功于自己。
    • 对 Spring 5 也有好处。我已经设法在 ConstraintValidatorServletUriComponentsBuilder.fromCurrentRequestUri().toUriString(); 中获取 URL。
    【解决方案3】:

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

    【讨论】:

    • 只提供主机名
    【解决方案4】:

    在jsp文件中:

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

    【讨论】:

      【解决方案5】:

      您还可以在控制器方法的方法签名中添加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)
      【解决方案6】:

      如果您需要 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

      【讨论】:

        【解决方案7】:

        System.out.println(((HttpServletRequest)request).getRequestURI());

        我用过。希望有用。

        【讨论】:

          猜你喜欢
          • 2010-09-08
          • 1970-01-01
          • 2018-03-17
          • 2018-10-25
          • 2013-03-23
          • 1970-01-01
          • 2016-01-30
          • 1970-01-01
          相关资源
          最近更新 更多