杰瑞科技汇

Java Web如何获取完整URL参数?

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

Java Web如何获取完整URL参数?-图1
(图片来源网络,侵删)

核心概念: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 对象来获取所有与请求相关的信息。

Java Web如何获取完整URL参数?-图2
(图片来源网络,侵删)

假设我们有如下一个 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() 获取协议类型 (httphttps)。 http
request.getServerName() 获取服务器主机名。 localhost
request.getServerPort() 获取服务器端口号。 8080

在 Spring Framework / Spring Boot 中获取 URL

Spring 框架对 Servlet API 进行了进一步的封装,使得获取信息更加方便。

a) 在 Controller 方法中获取 (最常用)

在 Spring MVC 中,Controller 方法的参数可以直接接收 HttpServletRequest 对象。

Java Web如何获取完整URL参数?-图3
(图片来源网络,侵删)
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) 使用 @RequestMappingpath 属性

如果你只是想知道当前请求匹配的是哪个 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 / @GetMappingpath 属性 用于代码逻辑判断,与具体请求无关。

对于初学者,掌握 HttpServletRequest 的几个核心方法是基础,对于 Spring 开发者,UriComponentsBuilder 是你必须掌握的瑞士军刀,而对于需要生成应用自身地址的场景,ServerProperties 则是最佳选择。

分享:
扫描分享到社交APP
上一篇
下一篇