下面我将从最基础的 Servlet 到主流的 Spring Boot,为你详细梳理获取 URL 的各种方法。

核心概念:URL 的组成部分
在开始之前,我们先明确一下一个完整 URL 的构成,这样在获取时才能更有针对性:
http://www.example.com:8080/path/to/resource?name=java&age=20#section1
- 协议:
http(或https) - 主机名:
www.example.com - 端口号:
8080(如果端口是 80 或 443,通常可以省略) - 路径:
/path/to/resource - 查询参数:
name=java&age=20 - 片段标识符:
section1(这部分通常由浏览器处理,后端一般无法直接获取)
在 Java Web 中,我们通常获取的是请求 URL,即客户端发起请求的完整地址。
在原生 Servlet 中获取 URL
在传统的 Java Web 应用(使用 javax.servlet API)中,我们通过 HttpServletRequest 对象来获取所有与请求相关的信息。

假设我们有如下一个 Servlet:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/user/profile") // 这个注解映射了 URL 路径
public class UserProfileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// --- 获取不同部分的 URL ---
// 1. 获取请求协议 + 主机名 + 端口号
// 结果: http://localhost:8080
String scheme = request.getScheme(); // "http"
String serverName = request.getServerName(); // "localhost"
int serverPort = request.getServerPort(); // 8080
String contextPath = request.getContextPath(); // 当前应用的上下文路径,如 /my-web-app
String baseUrl = scheme + "://" + serverName + ":" + serverPort + contextPath;
System.out.println("Base URL: " + baseUrl);
// 2. 获取客户端在请求行中指定的完整 URL
// 结果: http://localhost:8080/my-web-app/user/profile?userId=123
String requestUrl = request.getRequestURL().toString();
System.out.println("Request URL: " + requestUrl);
// 3. 获取请求行中的查询字符串部分(不带 ?)
// 结果: userId=123
String queryString = request.getQueryString();
System.out.println("Query String: " + queryString);
// 4. 获取 Servlet 的映射路径(即 @WebServlet 的值)
// 结果: /user/profile
String servletPath = request.getServletPath();
System.out.println("Servlet Path: " + servletPath);
// 5. 获取请求的 URI(上下文路径 + Servlet 路径 + 路径信息)
// 结果: /my-web-app/user/profile
String requestUri = request.getRequestURI();
System.out.println("Request URI: " + requestUri);
// --- 组合成一个完整的 URL ---
// 如果你想获取包含查询参数的完整 URL,可以这样组合
String fullUrl = requestUrl;
if (queryString != null && !queryString.isEmpty()) {
fullUrl += "?" + queryString;
}
System.out.println("Full URL with Query: " + fullUrl);
// ... 业务逻辑 ...
response.getWriter().write("Profile page for user: " + request.getParameter("userId"));
}
}
Servlet 中的关键方法:
| 方法 | 描述 | 示例输出 |
|---|---|---|
request.getRequestURL() |
获取请求的 完整 URL,但不包含查询参数。 | http://localhost:8080/my-web-app/user/profile |
request.getQueryString() |
获取查询字符串部分(即 后面的内容)。 | userId=123&role=admin |
request.getRequestURI() |
获取请求 URI,包含上下文路径和 Servlet 路径。 | /my-web-app/user/profile |
request.getContextPath() |
获取当前 Web 应用的上下文路径。 | /my-web-app |
request.getServletPath() |
获取映射到当前 Servlet 的路径。 | /user/profile |
request.getScheme() |
获取协议类型 (http 或 https)。 |
http |
request.getServerName() |
获取服务器主机名。 | localhost |
request.getServerPort() |
获取服务器端口号。 | 8080 |
在 Spring Framework / Spring Boot 中获取 URL
Spring 框架对 Servlet API 进行了进一步的封装,使得获取信息更加方便。
a) 在 Controller 方法中获取 (最常用)
在 Spring MVC 中,Controller 方法的参数可以直接接收 HttpServletRequest 对象。

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletRequest;
import java.net.URL;
@Controller
public class MyWebController {
@GetMapping("/hello")
public String sayHello(HttpServletRequest request, @RequestParam String name) {
// Spring Boot 内置了 Tomcat,默认端口是 8080
// 1. 获取完整请求 URL (不带查询参数)
String requestUrl = request.getRequestURL().toString();
System.out.println("Request URL: " + requestUrl);
// 2. 获取查询字符串
String queryString = request.getQueryString();
System.out.println("Query String: " + queryString);
// 3. 获取请求 URI
String requestUri = request.getRequestURI();
System.out.println("Request URI: " + requestUri);
// 4. Spring 提供了更便捷的工具类:org.springframework.web.util.UriComponentsBuilder
// 这个工具类非常强大,可以轻松解析和构建 URL
String fullUrlWithQuery = UriComponentsBuilder.fromRequest(request)
.build()
.toUriString();
System.out.println("Full URL with Query (UriComponentsBuilder): " + fullUrlWithQuery);
// 使用 UriComponentsBuilder 解析各个部分
UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(requestUrl);
if (queryString != null) {
uriBuilder.query(queryString);
}
UriComponents uriComponents = uriBuilder.build();
System.out.println("Host: " + uriComponents.getHost());
System.out.println("Port: " + uriComponents.getPort());
System.out.println("Path: " + uriComponents.getPath());
System.out.println("Query Params: " + uriComponents.getQueryParams());
return "hello"; // 返回视图名称
}
}
b) 使用 @RequestMapping 的 path 属性
如果你只是想知道当前请求匹配的是哪个 Controller 的哪个方法,可以直接查看代码。
@RestController
@RequestMapping("/api/v1/users") // 这是父级路径
public class UserController {
@GetMapping("/{id}") // 完整路径是 /api/v1/users/{id}
public String getUserById(@PathVariable Long id) {
// ...
return "User details for " + id;
}
}
c) 在过滤器、拦截器或组件中获取
在这些场景下,你同样可以通过 HttpServletRequest 对象来获取 URL。
示例:使用过滤器
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
@WebFilter("/*") // 过滤所有请求
public class LoggingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String url = httpRequest.getRequestURL().toString();
String queryString = httpRequest.getQueryString();
System.out.println("Request to: " + url + (queryString != null ? "?" + queryString : ""));
chain.doFilter(request, response); // 继续执行过滤器链
}
// ... 其他方法 ...
}
在 Spring Boot 中获取当前应用的根 URL
你需要获取的是你自己部署的应用的根 URL,而不是客户端请求的 URL,在生成的邮件链接或 API 文档中。
Spring Boot 提供了非常方便的方式。
a) 使用 ServerProperties
通过注入 ServerProperties 可以轻松获取服务器的配置信息。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
// 获取应用根 URL 的工具方法
public static String getApplicationBaseUrl() {
// 在实际应用中,这个方法可能需要通过 ApplicationContext 来获取 Bean
// 这里为了演示,直接返回一个硬编码的值
// 更好的方式是注入 ServerProperties
return "http://localhost:8080/my-app";
}
}
@RestController
class MyController {
@GetMapping("/api/info")
public String getInfo() {
// 假设这是你的应用根 URL
String appBaseUrl = MyApplication.getApplicationBaseUrl();
System.out.println("Application Base URL: " + appBaseUrl);
return "This application is running at: " + appBaseUrl;
}
}
b) 更推荐的方式:注入 ServerProperties
在 Spring Boot 中,你可以将服务器配置作为 Bean 注入。
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.stereotype.Component;
@Component
public class ServerConfig {
// 获取服务器配置信息
private final org.springframework.boot.web.server.ServerProperties serverProperties;
// 构造器注入
public ServerConfig(org.springframework.boot.web.server.ServerProperties serverProperties) {
this.serverProperties = serverProperties;
}
public String getApplicationBaseUrl() {
String scheme = "http"; // 可以根据实际情况判断是 http 还是 https
String host = serverProperties.getAddress() != null ? serverProperties.getAddress().getHostAddress() : "localhost";
int port = serverProperties.getPort();
String contextPath = serverProperties.getServlet().getContextPath();
return String.format("%s://%s:%d%s", scheme, host, port, contextPath);
}
}
然后在 Controller 中注入并使用这个 ServerConfig Bean。
总结与最佳实践
| 场景 | 推荐方法 | 说明 |
|---|---|---|
| 获取客户端请求的完整 URL | HttpServletRequest.getRequestURL() + getQueryString() |
最基础、最直接的方法,适用于所有 Servlet 容器。 |
| 在 Spring 中解析和构建 URL | UriComponentsBuilder.fromRequest(request) |
强烈推荐,Spring 提供的工具类,功能强大,能轻松处理 URL 的编码、拼接、解析等。 |
| 获取当前 Web 应用的上下文路径 | HttpServletRequest.getContextPath() |
用于构建应用内部的绝对路径。 |
| 获取当前应用的根 URL | 注入 ServerProperties |
用于生成外部链接(如邮件、API 文档),不依赖于任何请求。 |
| 获取请求的映射路径 | 查看 @RequestMapping / @GetMapping 的 path 属性 |
用于代码逻辑判断,与具体请求无关。 |
对于初学者,掌握 HttpServletRequest 的几个核心方法是基础,对于 Spring 开发者,UriComponentsBuilder 是你必须掌握的瑞士军刀,而对于需要生成应用自身地址的场景,ServerProperties 则是最佳选择。
