请求对象(request)由服务器创建,封装了客户端请求的所有信息。
体系结构
获取客户端相关信息
常用API如下:
- getRequestURL() – 返回请求的完整路径
- getRequestURI() – 返回请求行中的资源名
- getQueryString() – 返回请求路径中的参数
- getMethod() – 返回请求方式(GET、POST、PUT、DELETE、HEAD、OPTIONS、TRACE)
- getContextPath() – 返回应用上下文(即当前web应用虚拟目录名称)
- getServerPort() – 返回请求的端口号
- getRemoteAddr() – 返回请求的客户机IP
StringBuffer requestURL = request.getRequestURL();
// 统一完整路径名,包括协议,虚拟主机和资源,
// url:http://domain:port/context/resource
System.out.println("url:"+requestURL);
String uri=request.getRequestURI();
// 统一资源路径名 uri: context
System.out.println("uri:"+uri);
// 请求端口号
int port = request.getServerPort();
System.out.println("port:"+port);
// 请求路径中的参数
String qs = request.getQueryString();
System.out.println("qs:"+qs);
// 请求方式
String method = request.getMethod();
System.out.println(method);
// context
String contextPath = request.getContextPath();
System.out.println(contextPath);
// ip
String addr = request.getRemoteAddr();
System.out.println("addr:"+addr);
获取请求路径
常见API
- getContextPath() – 获取项目上下文名称
- getServletPath() – 获取请求资源名称
- getPathInfo() – 获取不包含contextPath和servletPath和请求参数的URI部分内容
上下文设置样例
配置项 | 配置详情 |
---|---|
Context Path | /ServletWeb |
Servlet Mapping | Pattern: /admin/*; Servlet: AdminServlet |
Servlet Mapping | Pattern: *.jsp; Servlet: JspServlet |
路径参数
请求路径 | 路径元素 |
---|---|
/ServletWeb/admin/index.html | ContextPath: /ServletWeb; ServletPath: /admin; PathInfo: /index.html |
/ServletWeb/admin/add | ContextPath: /ServletWeb; ServletPath: /admin; PathInfo: /add |
/ServletWeb/user/add.jsp | ContextPath: /ServletWeb; ServletPath: /user/add.jsp; PathInfo: null |
注意:
请求URI = contextPath + servletPath + pathInfo
获取请求头信息
客户端头信息
头信息 | 描述 | 样例 |
---|---|---|
Accept | 指定MIME类型 | text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.7 |
Accept-Charset | 指定字符集信息 | UTF-8 |
Accept-Encoding | 指定客户端字符编码 | gzip, deflate, br |
Accept-Language | 指定客户端首选语言 | zh-CN,zh;q=0.9 |
Authoriaztion | 身份识别信息 | |
Connection | 指定是否客户处理持久HTTP连接,即允许通过单个请求检索多个文件 | Keep-Alive(表示持续连接) |
Content-Length | 仅使用POST请求,POST提交数据大小 | |
Cookie | Cookie信息 | |
Host | 原始URL中的主机和端口 | |
Referer | 请求来源(可防盗链和恶意请求) | |
User-Agent | 请求客户端的信息 |
常用API如下:
- getHeader(String name) – 获取指定名称的头信息,返回一个字符串
- getHeaders(String name) – 获取指定名称的头信息,返回一个枚举
- getHeaderNames() – 获取全部的请求头名称,返回一个枚举
// 获取指定头的信息,返回字符串
String header = request.getHeader("Accept");
// header(Accept):text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
System.out.println("header(Accept):" + header);
// 获取指定头的信息,返回枚举
Enumeration<String> headers = request.getHeaders("Accept");
while (headers.hasMoreElements()) {
String element = headers.nextElement();
// header(Accept):text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
System.out.println("headers(Accept):" + element);
}
// 获取所有的头名称,返回枚举
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement();
/**
* headerName:localhost:8080
* headerName:keep-alive
* headerName:no-cache
* headerName:no-cache
* headerName:"Google Chrome";v="113", "Chromium";v="113", "Not-A.Brand";v="24"
* headerName:?0
* headerName:"macOS"
* headerName:1
* headerName:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36
* headerName:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng
* headerName:document
* headerName:gzip, deflate, br
* headerName:zh - CN, zh;q = 0.9
*/
System.out.println("headerName:" + request.getHeader(headerName));
}
获取请求参数信息
常用API如下
- getParameter(String name) – 根据name获取参数值(单个值)
- getParameterValues(String name) – 根据name获取参数值(多个值)
- getParameterMap() – 获取所有参数,将查询的参数保存在Map中
- getParameterNames() – 获取所有的参数名称,返回枚举
// 根据name获取参数值
String name = req.getParameter("name");
// name:admin
System.out.println("name:" + name);
// 根据name获取参数值
String[] hobbies = req.getParameterValues("hobby");
// hobbies:弹吉他,看书,打篮球
System.out.print("hobbies:");
for (String hobby : hobbies) {
System.out.print(hobby + ",");
}
System.out.println();
// 获取所有请求参数
Map<String, String[]> parameterMap = req.getParameterMap();
// name:admin,
// hobby:弹吉他,看书,打篮球,
for (String key : parameterMap.keySet()) {
String[] paramValues = parameterMap.get(key);
System.out.print(key + ":");
for (String value : paramValues) {
System.out.print(value + ",");
}
System.out.println();
}
// 获取所有参数名称
Enumeration<String> parameterNames = req.getParameterNames();
while (parameterNames.hasMoreElements()) {
String nextElement = parameterNames.nextElement();
System.out.println(nextElement);
}
注意:
获取请求参数值可能会存在中文乱码的情况,不同的请求方式处理乱码的方式也不一样。
- GET 由于GET的请求方式中,请求参数放在请求行中,通过request对象的setCharacterEncoding()方法设置编码格式的方式无效。系统默认字体编码格式为ISO-8859-1,所以必须通过**new String(paramerValue.getByte(“iso-8859-1”), “UTF-8”)**获取。
- POST 只需通过request对象的setCharacterEncoding()方法设置编码格式即可,即与浏览器中meta标签中的charset属性保持一致便可。
扩展:
HTTP请求编码方式
Content-Type类型 | 说明 |
---|---|
application/x-www-form-urlencoded | 以字符流方式传输,数据类型为FormData,GET请求时,将FormData数据转换为(name1=valuea&name2=value2...) 的形式,然后append到请求URL后;POST请求时,将FormData数据封装到请求Body中 |
application/json | 以JSON格式数据传输 |
multipart/form-data | 以字节流的方式传输(表单中有文件时,必须使用这种方式提交) |
text/plain | 以纯文本的形式进行编码,不含任何控件或格式字符 |
请求转发
使用request对象的RequestDispatcher资源调度,将请求从当前资源转交给下一个资源处理。转发是发生在服务端的行为,在转发过程中,只有一次请求和一次响应,并且地址不变。
public class Servlet004 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/servlet005");
response.getWriter().write("this is Servlet004");//请求转发前,向response缓冲区中写入数据,请求转发时,会将response缓冲区清空一次
/**
* 强行将缓冲区中的所有内容写入客户端。调用此方法会自动提交响应,这意味着将编写状态代码和头。后面再次转发会失败
* public void flushBuffer() throws java.io.IOException
*/
// response.flushBuffer();// 不会再执行转发后后的内容
System.out.println("... Servlet004 begin ...");
requestDispatcher.forward(request, response);
System.out.println("... Servlet004 end ...");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
public class Servlet005 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("this is Servlet005");
System.out.println("... Servlet005 begin ...");
request.getRequestDispatcher("/servlet006").forward(request, response);
System.out.println("... Servlet005 end ...");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
public class Servlet006 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("this is Servlet006");
System.out.println("... Servlet006 ...");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
/**
* 正常情况下,浏览器中显示,this is Servlet006,即最后一个资源的输出内容;控制台中 输出
* ... Servlet004 begin ...
* ... Servlet005 begin ...
* ... Servlet006 ...
* ... Servlet005 end ...
* ... Servlet004 end ...
*
* 若在请求转发方法前执行response.flushBuffer(),其后的方法便不会再执行,response也不会输出内容
*/
注意:
- 请求转发的资源只能是当前项目中的资源。
- 请求转发过程中