杰瑞科技汇

Java如何高效获取完整request URL?

下面我将分场景、分环境(Servlet 原生 API vs. Spring Boot)为你详细讲解如何获取这些信息。

Java如何高效获取完整request URL?-图1
(图片来源网络,侵删)

核心概念:HttpServletRequest 对象

获取 URL 的所有信息都依赖于 javax.servlet.http.HttpServletRequest 这个对象,在标准的 Servlet 应用中,你通常通过控制器方法的参数来接收它。

import javax.servlet.http.HttpServletRequest;
public class MyController {
    public void handleRequest(HttpServletRequest request) {
        // 在这里使用 request 对象获取 URL 信息
    }
}

在 Spring Boot 中,这个过程被简化了,你只需要在方法参数中声明 HttpServletRequest,Spring 会自动为你注入。


获取 URL 的各个组成部分

HttpServletRequest 提供了一系列方法来获取 URL 的不同部分,我们用一个示例 URL 来演示:

https://www.example.com:8080/path/to/resource?name=John&age=30#section1

Java如何高效获取完整request URL?-图2
(图片来源网络,侵删)

注意: 及其后面的部分(section1)是片段标识符(Fragment Identifier),它不会发送到服务器,因此无法通过 HttpServletRequest 获取。

目标信息 Servlet API 方法 示例 URL 中的值 说明
完整的请求 URI (包含协议、主机、端口、路径、查询参数) request.getRequestURL() https://www.example.com:8080/path/to/resource?name=John&age=30 返回一个 StringBuffer,包含从协议到查询字符串的所有内容。这是最常用的获取完整 URL 的方式。
请求路径 (不包含查询参数) request.getRequestURI() /path/to/resource 返回请求的 URI 部分,不包含查询参数。
查询字符串 request.getQueryString() name=John&age=30 返回 后面的字符串,不包含 本身,如果没有查询参数,返回 null
协议 request.getScheme() https 返回请求的协议,如 httphttps
服务器名称 request.getServerName() www.example.com 返回请求头 Host 中的主机名。
服务器端口 request.getServerPort() 8080 返回请求的端口号。
上下文路径 request.getContextPath() (可能为空字符串 ) 返回当前应用的上下文路径,如果应用部署在 myapp 下,则此处为 /myapp,在 Spring Boot 的嵌入式容器中,默认通常是空字符串。
Servlet 路径 request.getServletPath() (可能为空字符串 ) 返回匹配到 Servlet 的路径部分,在 Spring MVC 中,这通常与 @RequestMapping 的路径相关,但直接使用较少。

代码示例

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Enumeration;
public class UrlInfoExtractor {
    public void printUrlInfo(HttpServletRequest request) {
        // 1. 获取完整的请求 URL (最常用)
        StringBuffer requestUrl = request.getRequestURL();
        System.out.println("1. Request URL: " + requestUrl.toString());
        // 2. 获取请求 URI (路径部分)
        String requestUri = request.getRequestURI();
        System.out.println("2. Request URI: " + requestUri);
        // 3. 获取查询字符串
        String queryString = request.getQueryString();
        System.out.println("3. Query String: " + (queryString == null ? "N/A" : queryString));
        // 4. 获取协议
        String scheme = request.getScheme();
        System.out.println("4. Scheme: " + scheme);
        // 5. 获取服务器名称
        String serverName = request.getServerName();
        System.out.println("5. Server Name: " + serverName);
        // 6. 获取服务器端口
        int serverPort = request.getServerPort();
        System.out.println("6. Server Port: " + serverPort);
        // 7. 获取上下文路径
        String contextPath = request.getContextPath();
        System.out.println("7. Context Path: " + (contextPath.isEmpty() ? "\"\"" : contextPath));
        // 8. 获取Servlet路径
        String servletPath = request.getServletPath();
        System.out.println("8. Servlet Path: " + (servletPath.isEmpty() ? "\"\"" : servletPath));
        // 9. 获取所有请求头 (可以看到 Host 头)
        System.out.println("\n--- Request Headers ---");
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            System.out.println(headerName + ": " + request.getHeader(headerName));
        }
    }
}

不同环境下的使用方法

标准 Servlet 环境

如果你在使用原生的 Servlet API,比如在一个 HttpServletdoGetdoPost 方法中。

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class MyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        // 直接使用 req 对象
        String fullUrl = req.getRequestURL().toString();
        String query = req.getQueryString();
        System.out.println("Full URL: " + fullUrl);
        System.out.println("Query: " + query);
        resp.getWriter().write("URL information printed to console.");
    }
}

Spring Boot / Spring MVC 环境

在 Spring Boot 中,这变得非常简单,你只需要在 Controller 的方法参数中声明 HttpServletRequest

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@RestController
public class MySpringController {
    @GetMapping("/api/info")
    public String getUrlInfo(HttpServletRequest request) {
        // 创建一个 StringBuilder 来构建响应
        StringBuilder response = new StringBuilder();
        response.append("Full Request URL: ").append(request.getRequestURL()).append("<br>");
        response.append("Request URI: ").append(request.getRequestURI()).append("<br>");
        response.append("Query String: ").append(request.getQueryString() == null ? "N/A" : request.getQueryString()).append("<br>");
        response.append("Scheme: ").append(request.getScheme()).append("<br>");
        response.append("Server Name: ").append(request.getServerName()).append("<br>");
        response.append("Server Port: ").append(request.getServerPort()).append("<br>");
        response.append("Context Path: ").append(request.getContextPath()).append("<br>");
        return response.toString();
    }
}

当你访问 http://localhost:8080/api/info?name=test 时,浏览器会显示类似下面的内容:

Java如何高效获取完整request URL?-图3
(图片来源网络,侵删)
Full Request URL: http://localhost:8080/api/info
Request URI: /api/info
Query String: name=test
Scheme: http
Server Name: localhost
Server Port: 8080
Context Path: 

常见问题与注意事项

如何获取不含查询参数的完整 URL?

这是一个非常常见的需求。getRequestURL() 返回包含查询参数的 URL,而 getRequestURI() 不包含,我们可以将两者结合起来。

// HttpServletRequest request
StringBuffer urlBuffer = request.getRequestURL(); // 不包含查询参数
String queryString = request.getQueryString();    // 只包含查询参数
String fullUrlWithoutQuery = urlBuffer.toString();
if (queryString != null) {
    fullUrlWithoutQuery += "?" + queryString;
}
// 如果只想获取不含查询参数的 URL,直接使用 getRequestURL() 即可
String urlWithoutQuery = request.getRequestURL().toString();

getContextPath() 在 Spring Boot 中为什么是空的?

在 Spring Boot 的嵌入式 Tomcat (Jetty, Undertow) 中,应用通常部署在根路径 下。getContextPath() 返回一个空字符串 ,如果你的应用被部署在传统的 Servlet 容器(如 Tomcat)的某个子路径下(myapp),getContextPath() 就会返回 /myapp

如何处理中文或特殊字符?

URL 中的路径和查询参数可能会包含非 ASCII 字符(如中文),这些字符在传输时通常会被URL编码空格 -> %20 -> %E4%B8%AD)。

  • request.getRequestURI()request.getRequestURL() 返回的是已经解码的字符串,如果你需要原始的、编码后的字符串,你需要从请求头或路径中手动处理,但这通常不必要。
  • 如果你想获取原始的、未经解码的查询字符串,request.getQueryString() 返回的就是编码后的字符串。
  • 如果你想手动解码一个字符串,可以使用 java.net.URLDecoder
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
String encodedValue = "E4%B8%AD%E6%96%87";
String decodedValue = URLDecoder.decode(encodedValue, StandardCharsets.UTF_8.name());
// decodedValue 现在是 "中文"
你的目标 推荐方法
获取完整的请求 URL (包含查询参数) request.getRequestURL().toString()
获取请求路径 (不包含查询参数) request.getRequestURI()
获取查询字符串 (不包含 ) request.getQueryString()
获取协议、主机、端口等 分别使用 getScheme(), getServerName(), getServerPort()
在 Spring Boot 中获取 直接在 Controller 方法参数中注入 HttpServletRequest
分享:
扫描分享到社交APP
上一篇
下一篇