获取客户端的 IP 地址
这是更常见的需求,比如用于记录访问日志、做地域限制、防刷等。

客户端的 IP 地址可以通过 HttpServletRequest 对象获取,最直接的方法是 request.getRemoteAddr()。
基本方法:request.getRemoteAddr()
这是获取客户端 IP 最直接、最常用的方法,它返回的是客户端发起请求的最后一个代理的 IP 地址。
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ClientIpServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
String ipAddress = request.getRemoteAddr();
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("<h1>客户端 IP 地址</h1>");
response.getWriter().println("<p>使用 getRemoteAddr() 获取的 IP 地址是: <strong>" + ipAddress + "</strong></p>");
}
}
处理代理服务器(如 Nginx, Apache)的情况
当你的应用部署在反向代理(如 Nginx, Apache, HAProxy)后面时,request.getRemoteAddr() 获取到的将是代理服务器的 IP 地址,而不是客户端的真实 IP。
为了获取客户端的真实 IP,我们需要检查一个特殊的 HTTP 请求头:X-Forwarded-For。

X-Forwarded-For: 这个头字段用于记录 HTTP 请求经过的代理服务器列表,格式通常为客户端IP, 代理1IP, 代理2IP, ...,最左边的 IP 是客户端的真实 IP。
获取客户端真实 IP 的逻辑是:
- 首先检查
request.getHeader("X-Forwarded-For")。 - 如果该头存在且不为空,则取其第一个逗号左边的部分。
- 如果不存在,则回退到
request.getRemoteAddr()。
推荐使用一个工具类来封装这个逻辑,因为它比较复杂,且需要考虑多个代理头的情况(如 Proxy-Client-IP, WL-Proxy-Client-IP 等)。
示例:IP 获取工具类
import javax.servlet.http.HttpServletRequest;
public class IpUtils {
/**
* 获取客户端的真实 IP 地址
* @param request HttpServletRequest 对象
* @return 客户端真实 IP 地址
*/
public static String getClientIpAddress(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
// X-Forwarded-For 为空,则尝试获取 Proxy-Client-IP
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
// Proxy-Client-IP 为空,则尝试获取 WL-Proxy-Client-IP
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
// 如果以上都为空,则使用 getRemoteAddr() 获取
ip = request.getRemoteAddr();
}
// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
if (ip != null && ip.contains(",")) {
ip = ip.split(",")[0].trim();
}
return ip;
}
}
在 Servlet 中使用工具类

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RealClientIpServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
String realIp = IpUtils.getClientIpAddress(request);
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("<h1>客户端真实 IP 地址</h1>");
response.getWriter().println("<p>使用工具类获取的真实 IP 地址是: <strong>" + realIp + "</strong></p>");
}
}
获取服务器自身的 IP 地址
如果你想知道运行 Servlet 的那台服务器(物理机或虚拟机)的 IP 地址,你需要从服务器环境的上下文中获取。
获取服务器名称(主机名)
最简单的方法是获取服务器的主机名。
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class ServerInfoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 获取服务器名称(主机名)
String serverName = request.getServerName();
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("<h1>服务器信息</h1>");
response.getWriter().println("<p>服务器名称 (主机名): <strong>" + serverName + "</strong></p>");
}
}
获取服务器 IP 地址
要获取服务器绑定的 IP 地址,你需要结合 HttpServletRequest 和 java.net.InetAddress。
注意:一台服务器可能有多个网卡,绑定多个 IP 地址。request.getLocalAddr() 获取的是接收当前请求的那个网络接口的 IP 地址。
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class ServerIpServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 方法一:获取接收请求的本地网络接口的 IP 地址
String serverIp = request.getLocalAddr();
// 方法二:通过主机名获取所有 IP 地址(可以获取到服务器的所有 IP)
InetAddress localHost;
try {
localHost = InetAddress.getLocalHost();
// 如果想获取所有 IP 地址,可以使用 NetworkInterface 类
// 这里我们只获取主机名和默认 IP
String hostName = localHost.getHostName();
String allIps = localHost.getHostAddress(); // 这通常只返回一个 IP
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("<h1>服务器自身 IP 地址</h1>");
response.getWriter().println("<p>通过 request.getLocalAddr() 获取的 IP: <strong>" + serverIp + "</strong></p>");
response.getWriter().println("<p>通过 InetAddress.getLocalHost() 获取的主机名: <strong>" + hostName + "</strong></p>");
response.getWriter().println("<p>通过 InetAddress.getLocalHost() 获取的 IP: <strong>" + allIps + "</strong></p>");
} catch (UnknownHostException e) {
response.getWriter().println("无法获取服务器主机信息: " + e.getMessage());
}
}
}
| 需求 | 方法 | 说明 |
|---|---|---|
| 获取客户端 IP | request.getRemoteAddr() |
直接获取,但可能受代理影响,得到的是代理的 IP。 |
| 获取客户端真实 IP | request.getHeader("X-Forwarded-For") |
必须处理代理服务器场景,建议使用封装好的工具类。 |
| 获取服务器主机名 | request.getServerName() |
获取服务器配置的主机名或域名。 |
| 获取服务器 IP | request.getLocalAddr() |
获取接收当前请求的本地网络接口的 IP 地址。 |
| 获取服务器所有 IP | InetAddress.getLocalHost() 和 NetworkInterface |
获取服务器主机名和默认 IP,NetworkInterface 可用于获取所有 IP。 |
在实际开发中,请务必使用工具类来获取客户端真实 IP,因为你的应用几乎不可能直接暴露在公网,总会有反向代理存在。
