前言:HttpServletRequest对象封装了客户端进行HTTP协议请求时的所有信息,HttpServletRequest继承了ServletRequest,所以和ServletRequest一样,是由tomcat服务器提供实现的。具体过程如下:
1)Web客户向Servlet容器发出Http请求;
2)Servlet容器解析Web客户的Http请求;
3)Servlet容器创建一个HttpRequest对象,在这个对象中封装Http请求信息;
1.HttpServlet
说到HttpServletRequest就不得不说一下HttpServlet,下面看它的API:
javax.servlet.http
Class HttpServlet
java.lang.Object javax.servlet.GenericServlet javax.servlet.http.HttpServlet
-
All Implemented Interfaces:
- Serializable, Servlet, ServletConfig
Method Summary | |
---|---|
protected void | doDelete(HttpServletRequest req,HttpServletResponse resp) Called by the server (via the service method) to allow a servlet to handle a DELETE request. |
protected void | doGet(HttpServletRequest req,HttpServletResponse resp) Called by the server (via the service method) to allow a servlet to handle a GET request. |
protected void | doHead(HttpServletRequest req,HttpServletResponse resp) Receives an HTTP HEAD request from the protected service method and handles the request. |
protected void | doOptions(HttpServletRequest req,HttpServletResponse resp) Called by the server (via the service method) to allow a servlet to handle a OPTIONS request. |
protected void | doPost(HttpServletRequest req,HttpServletResponse resp) Called by the server (via the service method) to allow a servlet to handle a POST request. |
protected void | doPut(HttpServletRequest req,HttpServletResponse resp) Called by the server (via the service method) to allow a servlet to handle a PUT request. |
protected void | doTrace(HttpServletRequest req,HttpServletResponse resp) Called by the server (via the service method) to allow a servlet to handle a TRACE request. |
protected long | getLastModified(HttpServletRequest req) Returns the time the HttpServletRequest object was last modified, in milliseconds since midnight January 1, 1970 GMT. |
protected void | service(HttpServletRequest req,HttpServletResponse resp) Receives standard HTTP requests from the public service method and dispatches them to thedo XXX methods defined in this class. |
void | service(ServletRequest req,ServletResponse res) Dispatches client requests to the protected service method. |
service(ServletRequest req,ServletResponse res)
方法和servlet中的一致,在每次请求时调用。只抽取部分方法,概要信息如下:
(1).doGet(HttpServletRequest req,HttpServletResponse resp)
:接收HTTP的GET请求;
(2).doPost(HttpServletRequest req,HttpServletResponse resp)
:接收HTTP的POST请求;
(3).service(HttpServletRequest req,HttpServletResponse resp)
:接收HTTP请求,并把它分配到doXXX方法中;
2.HttpServletRequest的API:
javax.servlet.http
Interface HttpServletRequest
-
All Superinterfaces:
- ServletRequest
-
All Known Implementing Classes:
- HttpServletRequestWrapper
String | getAuthType() Returns the name of the authentication scheme used to protect the servlet. |
String | getContextPath() Returns the portion of the request URI that indicates the context of the request. |
Cookie[] | getCookies() Returns an array containing all of the Cookie objects the client sent with this request. |
long | getDateHeader(String name) Returns the value of the specified request header as a long value that represents aDate object. |
String | getHeader(String name) Returns the value of the specified request header as a String . |
Enumeration | getHeaderNames() Returns an enumeration of all the header names this request contains. |
Enumeration | getHeaders(String name) Returns all the values of the specified request header as an Enumeration ofString objects. |
int | getIntHeader(String name) Returns the value of the specified request header as an int . |
String | getMethod() Returns the name of the HTTP method with which this request was made, for example, GET, POST, or PUT. |
String | getPathInfo() Returns any extra path information associated with the URL the client sent when it made this request. |
String | getPathTranslated() Returns any extra path information after the servlet name but before the query string, and translates it to a real path. |
String | getQueryString() Returns the query string that is contained in the request URL after the path. |
String | getRemoteUser() Returns the login of the user making this request, if the user has been authenticated, or null if the user has not been authenticated. |
String | getRequestedSessionId() Returns the session ID specified by the client. |
String | getRequestURI() Returns the part of this request's URL from the protocol name up to the query string in the first line of the HTTP request. |
StringBuffer | getRequestURL() Reconstructs the URL the client used to make the request. |
String | getServletPath() Returns the part of this request's URL that calls the servlet. |
HttpSession | getSession() Returns the current session associated with this request, or if the request does not have a session, creates one. |
HttpSession | getSession(boolean create) Returns the current HttpSession associated with this request or, if there is no current session andcreate is true, returns a new session. |
Principal | getUserPrincipal() Returns a java.security.Principal object containing the name of the current authenticated user. |
boolean | isRequestedSessionIdFromCookie() Checks whether the requested session ID came in as a cookie. |
boolean | isRequestedSessionIdFromUrl() Deprecated. As of Version 2.1 of the Java Servlet API, use isRequestedSessionIdFromURL() instead. |
boolean | isRequestedSessionIdFromURL() Checks whether the requested session ID came in as part of the request URL. |
boolean | isRequestedSessionIdValid() Checks whether the requested session ID is still valid. |
boolean | isUserInRole(String role) Returns a boolean indicating whether the authenticated user is included in the specified logical "role". |
这里只列举常用的几个方法(有些API中没有列举到的,是在ServletRequest中已有的方法):
(1)获得客户机信息
:返回客户端发出请求时的完整URL。getRequestURL()
getRequestURI()
:返回请求行中的资源名部分。getQueryString()
:返回请求行中的参数部分。getRemoteAddr()
:返回发出请求的客户机的IP地址。getRemoteHost()
:返回发出请求的客户机的完整主机名。getRemotePort()
:返回客户机所使用的网络端口号。getLocalAddr()
:返回WEB服务器的IP地址。getLocalName()
:返回WEB服务器的主机名。
(2)获得客户机请求头 getHeaders(String name)
:获得请求头信息组成的Enumeration。
(3)获得客户机请求参数(客户端提交的数据) getParameterMap():获取参数名和参数值的
String[]组成的键值对,即返回的类型为
Map(
String
,String[]
),用于多参数值。
3.项目的目录结构
4.web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>javaWeb_07</display-name>
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>httpRequestDemo</servlet-name>
<servlet-class>com.dao.chu.HttpRequestDemo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>httpRequestDemo</servlet-name>
<url-pattern>/httpRequest</url-pattern>
</servlet-mapping>
</web-app>
5.login.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>登陆页</title>
</head>
<body>
<!-- 相对路径写action="httpRequest"; -->
<!-- 绝对路径写action="/javaWeb_07/httpRequest"; -->
<form action="httpRequest" method="get">
用户名:<input type="text" name="user">
<br><br>
密码 <input type="password" name="password">
<br><br>
<!-- 一组信息 -->
interesting:
<input type="checkbox" name="interesting" value="reading">Reading
<input type="checkbox" name="interesting" value="writing">Writing
<input type="checkbox" name="interesting" value="football">Football
<input type="checkbox" name="interesting" value="game">Game
<input type="checkbox" name="interesting" value="shopping">Shopping
<input type="checkbox" name="interesting" value="party">Party
<input type="checkbox" name="interesting" value="TV">TV
<br><br>
<input type="submit" value="提交">
</form>
</body>
</html>
6.HttpRequestDemo.java,分三种情况,对应后面的三种现象
(1)只写一个service方法
package com.dao.chu;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* <p>
* Title: HttpRequestDemo Description:继承了HttpServlet的测试类
* </p>
*/
public class HttpRequestDemo extends HttpServlet {
/** serialVersionUID */
private static final long serialVersionUID = 1L;
// 得到请求的URL地址
String requestUrl = "";
// 得到请求行中的资源部分
String requestUri = "";
// 得到请求的URL地址中附带的参数
String queryString = "";
// 得到来访者的IP地址
String remoteAddr = "";
// 来访者主机名
String remoteHost = "";
// 客户机所使用的网络端口号
int remotePort = 0;
// 得到请求方式GET/POST
String method = "";
// 获取WEB服务器的IP地址
String localAddr = "";
// 获取WEB服务器的主机名
String localName = "";
/**
* 继承了HttpServlet的service方法
*/
@Override
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
//调用公共输出方法
commonPrint(request, response);
}
/**
* Title: commonPrint
* Description:公共输出方法
* @param request
* @param response
*/
private void commonPrint(HttpServletRequest request,
HttpServletResponse response) {
// 设置将字符以"UTF-8"编码输出到客户端浏览器
response.setCharacterEncoding("UTF-8");
// 通过设置响应头控制浏览器以UTF-8的编码显示数据,如果不加这句话,那么浏览器显示的将是乱码
response.setHeader("content-type", "text/html;charset=UTF-8");
requestUrl = request.getRequestURL().toString();
requestUri = request.getRequestURI();
queryString = request.getQueryString();
remoteAddr = request.getRemoteAddr();
method = request.getMethod();
localAddr = request.getLocalAddr();
localName = request.getLocalName();
PrintWriter out;
try {
out = response.getWriter();
out.write("<hr/>");
out.write("(1)获取客户机信息:");
out.write("<br/>");
out.write("请求的URL地址:" + requestUrl);
out.write("<br/>");
out.write("请求的资源:" + requestUri);
out.write("<br/>");
out.write("请求的URL地址中附带的参数:" + queryString);
out.write("<br/>");
out.write("来访者的IP地址:" + remoteAddr);
out.write("<br/>");
out.write("来访者的主机名:" + remoteHost);
out.write("<br/>");
out.write("使用的端口号:" + remotePort);
out.write("<br/>");
out.write("请求的方式:" + method);
out.write("<br/>");
out.write("服务器的IP地址:" + localAddr);
out.write("<br/>");
out.write("服务器的主机名:" + localName);
// 获取的客户机的请求头信息
out.write("<br/>");
out.write("<hr/>");
out.write("(2)获取客户机的请求头信息:");
out.write("<br/>");
// 得到所有请求头名组成的Enumeration
Enumeration<String> headerNames = request.getHeaderNames();
// 循环
while (headerNames.hasMoreElements()) {
// 得到所有的请求头名
String headerName = (String) headerNames.nextElement();
// 根据请求头名得到所有请求头值
String headerValue = request.getParameter(headerName);
out.write(headerName + ": " + headerValue);
out.write("<br/>");
}
// 获取的客户机的请求信息
out.write("<br/>");
out.write("<hr/>");
out.write("(3)获取客户机的请求信息:");
out.write("<br/>");
// 获取参数名和参数值的String[]组成的键值对
Map<String, String[]> map = request.getParameterMap();
Set<Entry<String, String[]>> entrySet = map.entrySet();
for (Entry<String, String[]> entry : entrySet) {
out.write(entry.getKey() + ": "
+ Arrays.asList(entry.getValue()));
out.write("<br/>");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
(2)写有service方法,doget方法,dopost方法
package com.dao.chu;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* <p>
* Title: HttpRequestDemo Description:继承了HttpServlet的测试类
* </p>
*/
public class HttpRequestDemo extends HttpServlet {
/** serialVersionUID */
private static final long serialVersionUID = 1L;
// 得到请求的URL地址
String requestUrl = "";
// 得到请求行中的资源部分
String requestUri = "";
// 得到请求的URL地址中附带的参数
String queryString = "";
// 得到来访者的IP地址
String remoteAddr = "";
// 来访者主机名
String remoteHost = "";
// 客户机所使用的网络端口号
int remotePort = 0;
// 得到请求方式GET/POST
String method = "";
// 获取WEB服务器的IP地址
String localAddr = "";
// 获取WEB服务器的主机名
String localName = "";
/**
* 继承了HttpServlet的service方法
*/
@Override
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
System.out.println("调用了service方法");
//调用公共输出方法
commonPrint(request, response);
}
/**
* 继承了HttpServlet的doGet方法
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("调用了doGet方法");
//调用公共输出方法
commonPrint(request, response);
}
/**
* 继承了HttpServlet的doPost方法
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("调用了doPost方法");
//调用公共输出方法
commonPrint(request, response);
}
/**
* Title: commonPrint
* Description:公共输出方法
* @param request
* @param response
*/
private void commonPrint(HttpServletRequest request,
HttpServletResponse response) {
// 设置将字符以"UTF-8"编码输出到客户端浏览器
response.setCharacterEncoding("UTF-8");
// 通过设置响应头控制浏览器以UTF-8的编码显示数据,如果不加这句话,那么浏览器显示的将是乱码
response.setHeader("content-type", "text/html;charset=UTF-8");
requestUrl = request.getRequestURL().toString();
requestUri = request.getRequestURI();
queryString = request.getQueryString();
remoteAddr = request.getRemoteAddr();
method = request.getMethod();
localAddr = request.getLocalAddr();
localName = request.getLocalName();
PrintWriter out;
try {
out = response.getWriter();
out.write("<hr/>");
out.write("(1)获取客户机信息:");
out.write("<br/>");
out.write("请求的URL地址:" + requestUrl);
out.write("<br/>");
out.write("请求的资源:" + requestUri);
out.write("<br/>");
out.write("请求的URL地址中附带的参数:" + queryString);
out.write("<br/>");
out.write("来访者的IP地址:" + remoteAddr);
out.write("<br/>");
out.write("来访者的主机名:" + remoteHost);
out.write("<br/>");
out.write("使用的端口号:" + remotePort);
out.write("<br/>");
out.write("请求的方式:" + method);
out.write("<br/>");
out.write("服务器的IP地址:" + localAddr);
out.write("<br/>");
out.write("服务器的主机名:" + localName);
// 获取的客户机的请求头信息
out.write("<br/>");
out.write("<hr/>");
out.write("(2)获取客户机的请求头信息:");
out.write("<br/>");
// 得到所有请求头名组成的Enumeration
Enumeration<String> headerNames = request.getHeaderNames();
// 循环
while (headerNames.hasMoreElements()) {
// 得到所有的请求头名
String headerName = (String) headerNames.nextElement();
// 根据请求头名得到所有请求头值
String headerValue = request.getParameter(headerName);
out.write(headerName + ": " + headerValue);
out.write("<br/>");
}
// 获取的客户机的请求信息
out.write("<br/>");
out.write("<hr/>");
out.write("(3)获取客户机的请求信息:");
out.write("<br/>");
// 获取参数名和参数值的String[]组成的键值对
Map<String, String[]> map = request.getParameterMap();
Set<Entry<String, String[]>> entrySet = map.entrySet();
for (Entry<String, String[]> entry : entrySet) {
out.write(entry.getKey() + ": "
+ Arrays.asList(entry.getValue()));
out.write("<br/>");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
(3)写有service方法,doget方法,dopost方法,且service方法调用了父类的service(HttpServletRequest req,HttpServletResponse resp)
方法。
package com.dao.chu;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
*
* <p>
* Title: HttpRequestDemo Description:继承了HttpServlet的测试类
* </p>
*/
public class HttpRequestDemo extends HttpServlet {
/** serialVersionUID */
private static final long serialVersionUID = 1L;
// 得到请求的URL地址
String requestUrl = "";
// 得到请求行中的资源部分
String requestUri = "";
// 得到请求的URL地址中附带的参数
String queryString = "";
// 得到来访者的IP地址
String remoteAddr = "";
// 来访者主机名
String remoteHost = "";
// 客户机所使用的网络端口号
int remotePort = 0;
// 得到请求方式GET/POST
String method = "";
// 获取WEB服务器的IP地址
String localAddr = "";
// 获取WEB服务器的主机名
String localName = "";
/**
* 继承了HttpServlet的service方法
*/
@Override
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
System.out.println("调用了service方法");
//调用公共输出方法
commonPrint(request, response);
//依旧调用父类的方法
super.service(request, response);
}
/**
* 继承了HttpServlet的doGet方法
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("调用了doGet方法");
//调用公共输出方法
commonPrint(request, response);
}
/**
* 继承了HttpServlet的doPost方法
*/
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println("调用了doPost方法");
//调用公共输出方法
commonPrint(request, response);
}
/**
* Title: commonPrint
* Description:公共输出方法
* @param request
* @param response
*/
private void commonPrint(HttpServletRequest request,
HttpServletResponse response) {
// 设置将字符以"UTF-8"编码输出到客户端浏览器
response.setCharacterEncoding("UTF-8");
// 通过设置响应头控制浏览器以UTF-8的编码显示数据,如果不加这句话,那么浏览器显示的将是乱码
response.setHeader("content-type", "text/html;charset=UTF-8");
requestUrl = request.getRequestURL().toString();
requestUri = request.getRequestURI();
queryString = request.getQueryString();
remoteAddr = request.getRemoteAddr();
method = request.getMethod();
localAddr = request.getLocalAddr();
localName = request.getLocalName();
PrintWriter out;
try {
out = response.getWriter();
out.write("<hr/>");
out.write("(1)获取客户机信息:");
out.write("<br/>");
out.write("请求的URL地址:" + requestUrl);
out.write("<br/>");
out.write("请求的资源:" + requestUri);
out.write("<br/>");
out.write("请求的URL地址中附带的参数:" + queryString);
out.write("<br/>");
out.write("来访者的IP地址:" + remoteAddr);
out.write("<br/>");
out.write("来访者的主机名:" + remoteHost);
out.write("<br/>");
out.write("使用的端口号:" + remotePort);
out.write("<br/>");
out.write("请求的方式:" + method);
out.write("<br/>");
out.write("服务器的IP地址:" + localAddr);
out.write("<br/>");
out.write("服务器的主机名:" + localName);
// 获取的客户机的请求头信息
out.write("<br/>");
out.write("<hr/>");
out.write("(2)获取客户机的请求头信息:");
out.write("<br/>");
// 得到所有请求头名组成的Enumeration
Enumeration<String> headerNames = request.getHeaderNames();
// 循环
while (headerNames.hasMoreElements()) {
// 得到所有的请求头名
String headerName = (String) headerNames.nextElement();
// 根据请求头名得到所有请求头值
String headerValue = request.getParameter(headerName);
out.write(headerName + ": " + headerValue);
out.write("<br/>");
}
// 获取的客户机的请求信息
out.write("<br/>");
out.write("<hr/>");
out.write("(3)获取客户机的请求信息:");
out.write("<br/>");
// 获取参数名和参数值的String[]组成的键值对
Map<String, String[]> map = request.getParameterMap();
Set<Entry<String, String[]>> entrySet = map.entrySet();
for (Entry<String, String[]> entry : entrySet) {
out.write(entry.getKey() + ": "
+ Arrays.asList(entry.getValue()));
out.write("<br/>");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
7.填写jsp页面表单,发出HTTP请求
8.三种情况的现象
(1)页面显示
控制台无输出,说明成功调用了service方法。
(2)页面显示
控制台输出:
说明虽然写了dopost和doget方法,但是却没有接收到请求。
(3)页面显示
控制台打印:
很显然这次接收到了doGET方法
8.为了追求根源,我们找到HttpServlet的service方法的源码:
/**
* <p>Title: HttpServlet的service方法的源码</p>
* <p>Description: </p>
* @throws ServletException
* @throws IOException
*/
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String method = req.getMethod();
if (method.equals("GET")) {
long lastModified = getLastModified(req);
if (lastModified == -1L) {
doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader("If-Modified-Since");
} catch (IllegalArgumentException iae) {
ifModifiedSince = -1L;
}
if (ifModifiedSince < lastModified / 1000L * 1000L) {
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);
} else if (method.equals("POST")) {
doPost(req, resp);
} else if (method.equals("PUT")) {
doPut(req, resp);
} else if (method.equals("DELETE")) {
doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
doOptions(req, resp);
} else if (method.equals("TRACE")) {
doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
我们可以看到
String method = req.getMethod();if (method.equals("GET")){doGet(req, resp);}等
的确有接收请求的方式,根据判断的请求方式转到相应的方法。而我们在(2)中继承了HttpServlet,覆盖了service方法,没有调用原来父类的方法,所以即使写了doget和dopost也接收不到请求。
附:
本次项目源码:点击打开链接