Servlet API中,有一个HttpServletRequest接口(继承自ServletRequest接口),专门用来封装HTTP请求消息。其中定义了获取请求行、请求头和请求消息体的相关方法(对应HTTP请求消息中的:请求行、请求消息头和请求消息体三部分)。
HttpServletRequest接口
访问Servlet时,请求消息的请求行中包含:请求方法、请求资源名、请求路径等信息。
请求行
HttpServletRequest接口中,定义了一系列用于获取请求行的方法:
String getMethod()
:获取HTTP请求消息中的请求方式(如GET、POST等);String getRequestURI()
:获取请求行中资源名称部分,即位于URL的主机和端口之后、参数部分之前的部分;String getQueryString()
:获取请求行中的参数部分,也就是资源路径后面问号(?)以后的所有内容;String getProtocol()
:获取请求行中的协议名和版本(如HTTP/1.0或HTTP/1.1);String getScheme()
:获取请求的协议名(如http、https或ftp);String getContextPath()
:获取请求URL中属于WEB应用程序的路径,这个路径以“/”开头,表示相对于整个WEB站点的根目录,路径结尾不含“/”;String getServletPath()
:获取Servlet所映射的路径(url-pattern);
消息头
HttpServletRequest接口中,定义了一系列用于获取HTTP请求头字段的方法:
String getHeader(String name)
:获取一个指定头字段的值,如果请求消息中没有包含指定的头字段,getHeader()方法返回null;如果请求消息中包含有多个指定名称的头字段,getHeader()方法返回其中第一个头字段的值;Enumeration getHeaders(String name)
:返回一个Enumeration集合对象,该集合对象由请求消息中出现的某个指定名称的所有头字段值组成;Enumeration getHeaderNames()
:获取一个包含所有请求头字段的Enumeration对象int getIntHeader(String name)
:获取指定名称的头字段,并且将其值转为int类型(如果指定名称的头字段不存在,返回值为-1;如果获取到的头字段的值不能转为int类型,将发生NumberFormatException异常);Long getDateHeader(String name)
:获取指定头字段的值,并将其按GMT时间格式转换成UNIX时间戳(毫秒数);
请求参数
HttpServletRequest接口中,定义了一系列获取请求参数的方法:
String getParameter(String name)
:获取某个指定名称的参数值,如果请求消息中没有包含指定名称的参数,getParameter()方法返回null;String[] getParameterValues(String name)
:获得同一个参数名所对应的所有参数值;Enumeration getParameterNames()
:获得请求消息中所有参数名的Enumeration对象Map getParameterMap()
:获得参数名和值的Map对象;
请求源地址
通过HttpServletRequest,可以获取请求源的IP地址,方便调试与记录。
获取源地址
客户端的一个请求,在到达服务端前,可能会经过多次转发(包括Ngix等),我们只能尽快能尝试获取请求来源:
public static String getRequestIP(HttpServletRequest request) {
final String UnknownIP = "unknown";
final String LoopbackIP = "127.0.0.1";
String strAddr = null;
try {
strAddr = request.getHeader("x-forwarded-for");
if (strAddr == null || strAddr.length() == 0 || UnknownIP.equalsIgnoreCase(strAddr)) {
strAddr = request.getHeader("Proxy-Client-IP");
}
if (strAddr == null || strAddr.length() == 0 || UnknownIP.equalsIgnoreCase(strAddr)) {
strAddr = request.getHeader("WL-Proxy-Client-IP");
}
if (strAddr == null || strAddr.length() == 0 || UnknownIP.equalsIgnoreCase(strAddr)) {
strAddr = request.getRemoteAddr();
if (LoopbackIP.equals(strAddr)) {
// 根据网卡取本机配置的IP
InetAddress inet = null;
try {
inet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
strAddr = inet.getHostAddress();
}
}
// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
if (strAddr != null && strAddr.length() > 15) { // "***.***.***.***".length()
if (strAddr.indexOf(",") > 0) {
strAddr = strAddr.substring(0, strAddr.indexOf(","));
}
}
} catch (Exception e) {
strAddr = "";
}
return strAddr;
}
RestAPI接口调用
默认情况下,swagger-RestAPI接口中只列出请求相关的参数:
@RestController
@RequestMapping("test")
public class TestController {
@PostMapping("testPostData")
ResponseResult testPostData(String name, @RequestBody String request){
}
}
通过@RequestBody修饰的参数会放在body中传递,其他参数放在Header中。
为了获取请求相关数据,需要在参数中增加HttpServletRequest(其他参数不变,客户端请求调用也无任何影响):
@PostMapping("testPostData")
ResponseResult testPostData(HttpServletRequest servlet, String name, @RequestBody String request){
String strIP = getRequestIP(servlet);
}