请求与响应的基本知识
请求(request)
一个HTTP的请求由3部分组成:请求行、请求头、请求体
请求行
位置:请求信息的第一行
格式:请求的方式(GET/POST) 请求的资源 协议/版本(e.g. GET /xjm/1.html HTTP/1.1)
请求方式有两种:
get
- 会将参数追加在地址栏上,参数大小有限制
- e.g. http://ip地址:端口号/项目名/资源?参数名称=值&参数名称=值
post
- 不会将参数追加在地址栏,请求的参数在请求体中,参数的大小无限制
- e.g. 参数名称=值&参数名称=值
请求头
位置:请求行的下方,请求体的上方,与请求体有一个空行相隔。
格式为:key/value (value可以为多个值的)
常用的请求头(红色的是比较重要的):
key | e.g. | 含义 |
---|---|---|
Accept | text/html,image/* | 支持数据类型 mime类型 |
Accept-Language | zh-cn | –语言环境 |
If-Modified-Since | Sun, 10 Feb 2019 21:47:51 GMT | 缓存文件的最后修改时间 |
Accept-Encoding | gzip | 支持压缩 |
Accept-Charset | ISO-8859-1 | 字符集 |
Referer | http://www.csdn.net/index.html | 来自哪个页面、防盗链 |
Host | localhost | 请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。 |
User-Agent | Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0) | 产生请求的浏览器内核 |
Cookie | 会话技术 | |
Connection | close/Keep-Alive | 链接状态 |
请求体
位置:在请求头下面,和请求头之间有一个空行。
是post请求的参数,由于get方法中的参数在请求行中显示,因此get方法中请求体这部分为空。
格式:参数名称=值&参数名称=值(e.g. username=tom&hobby=smoking&hobby=drink)
响应(response)
与请求相类似,一个HTTP的响应也由3部分组成:响应行、响应头、响应体
响应行
位置:响应信息的第一行
格式:版本/协议 响应的状态码 状态码说明(e.g. HTTP/1.1 200 OK)
常见的状态码:
200 响应成功
302 重定向
304 读缓存
404 用户访问的数据不存在
500 服务器内部错误
响应头
位置:响应行的下方,响应体的上方,与响应体有一个空行相隔。
与请求头一样,格式为:key/value (value可以为多个值的)
常用的响应头(红色的是比较重要的):
key | e.g. | 含义 |
---|---|---|
Pragma | no-cache | 缓存 |
Connection | Keep-Alive | 连接 |
Cache-Control | no-cache | 缓存 |
Expires | -1 | 缓存 |
Set-Cookie | SS=Q0=5Lb_nQ; path=/search | |
Content-Disposition | attachment; filename=aaa.zip | 下载 |
Content-Language | zh-cn | 语言环境 |
Refresh | 1;url=http://www.it315.org | 定时刷新 |
Last-Modified | Sun, 10 Feb 2019 21:47:51 GMT | 最后修改时间 |
Content-Type | text/html; charset=GB2312 | 数据类型 |
Content-Length | 80 | 数据长度 |
Content-Encoding | gzip | 数据压缩 |
Server | apache tomcat | 服务器型号 |
Location | http://www.it315.org/index.jsp | 跳转方向 |
响应体
位置:在请求头下面,和请求头之间有一个空行,是浏览器解析的内容。
相关API介绍
请求行、头、体数据的读取
方法标签 | |
---|---|
请求行 | |
String getMethod() | 获取请求的方式 |
String getContextPath() | 获取项目动态路径 |
String getRemoteAddr() | 获取请求者的ip |
请求头 | |
String getHeader(String name) | 获取的一个请求头(返回值为string) |
请求体 | 同时适用于get和post方法 |
Map<String,String[]> getParameterMap() | 获取的所有的参数名称和值 |
String[] getParameterValues(String name) | 获取的指定请求参数(多值) |
String getParameter(String name) | 获取的单值的请求参数 |
请求中文乱码、请求转发、request域对象
请求中文乱码
因为浏览器中使用的是iso8859-1编码方式,请求中使用utf-8,所以读取中文时需要处理乱码问题。
通用的方式:
new String(乱码.getBytes("iso8859-1"), "utf-8");
针对post请求:
request.setCharacterEncoding("utf-8");
请求转发
作用:两个资源可以在同一次请求之间,进行资源共享。
request.getRequestDispatcher("/内部路径").forward(request,response);
该方法可以将当前servlet中的request和response发送到另一个servlet中进行处理。
request域对象
request域对象:
域对象:在一个访问(请求来时创建,生成响应时销毁)内有效,并且域对象都有xxxAttribute()方法
API |
---|
request.setAttribute(name, value) |
request.getAttribute(name) |
request.removeAttribute(name) |
响应行、头、体数据的读取
方法标签 | |
---|---|
响应行 | |
void setStatus(int code) | 针对1xx 2xx 3xx的相关状态码 |
void sendError(int code) | 针对4xx 5xx相关的错误状态码 |
响应头 | |
void setHeader(String name,String value) | 设置一个字符串形式的响应头 |
响应体 | |
ServletOutputStream getOutputStream() | 字节流 |
PrintWriter getWriter() | 字符流 |
响应的中文乱码
响应信息也会因为编码问题而出现中文乱码的问题,下面这种方法就能处理这种现象:
response.setContentType(“文件的mime类型;charset=utf-8”);
上下文(servletContext)
用来获取全局初始化参数,实现资源共享(servlet通信)。
生命周期:
- 创建:服务器启动的时候会为每个项目创建一个servletContext上下文对象,servleContext是项目的一个引用。
- 销毁:在服务器关闭或者移除项目的时候servletContext销毁。
API | |
---|---|
ServletContext getServletContext() | 获取上下文对象的方法 |
InputStream getResourceAsStream(String filepath) | 以流的方式返回一个文件 |
String getMimeType(String 文件名) | 获取一个文件的mime类型 e.g. text/html image/gif |
void removeAttribute(String name) | 移除指定的属性 |
void getAttribute(String name) | 获取指定的属性值 |
void setAttribute(String name,Object value) | 设置指定的属性值 |
代码示例
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" http-equiv="refresh" content="30;url=/xjm/index.html">
<title>功能页</title>
<script type="text/javascript">
var time = 30;
window.onload = function () {
window.setInterval(refresh,1000);
}
function refresh() {
time--;
document.getElementById("times").innerText=time;
}
</script>
</head>
<body>
<h1>请求响应信息</h1>
<h2>GET方法发送请求</h2>
<form method="get" action="/xjm/request">
用户名:<input type="text" name="username" value="xjm"/><br/>
密码:<input type="password" name="password" value="123"/><br/>
姓名:<input type="text" name="name"/><br/>
年龄:<input type="text" name="age"/><br/>
性别:<input type="radio" name="sex" value="1"/>男
<input type="radio" name="sex" value="0"/>女
<br/>
兴趣爱好:<input type="checkbox" name="hobby" value="踢足球"/>踢足球
<input type="checkbox" name="hobby" value="玩手游"/>玩手游
<input type="checkbox" name="hobby" value="逛街"/>逛街
<br/>
<input type="submit" value="get方式提交"/>
</form>
<br/><hr/>
<h2>POST方法提交请求</h2>
<form method="post" action="/xjm/request">
用户名:<input type="text" name="username" value="xjm"/><br/>
密码:<input type="password" name="password" value="123"/><br/>
姓名:<input type="text" name="name"/><br/>
年龄:<input type="text" name="age"/><br/>
性别:<input type="radio" name="sex" value="1"/>男
<input type="radio" name="sex" value="0"/>女
<br/>
兴趣爱好:<input type="checkbox" name="hobby" value="踢足球"/>踢足球
<input type="checkbox" name="hobby" value="玩手游"/>玩手游
<input type="checkbox" name="hobby" value="逛街"/>逛街
<br/>
<input type="submit" value="post方式提交"/>
</form>
<br/><hr/>
<h1>上下文示例</h1>
<a href="/xjm/count">记录访问次数</a>
<a href="/xjm/show">显示访问次数</a>
<br/><hr/>
<h1>响应头刷新</h1>
<span id="times">30</span>秒后会刷新本页面
</body>
</html>
RequestServlet.java
package request;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLDecoder;
public class RequestServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//解决请求的中文乱码
request.setCharacterEncoding("utf-8");
//解决响应的中文乱码
response.setContentType("text/html;charset=utf-8");
//请求行信息
response.getWriter().println("请求行信息:<br/>");
response.getWriter().println("请求的方式:" + request.getMethod() + "<br/>");
response.getWriter().println("请求动态路径:" + request.getContextPath() + "<br/>");
response.getWriter().println("请求的ip:" + request.getRemoteAddr() + "<br/>");
response.getWriter().println("请求的资源:" + request.getRequestURI() + "<br/>");
response.getWriter().println("获取请求的参数:" + request.getQueryString() + "<br/>");
response.getWriter().println("获取请求协议和版本:" + request.getProtocol() + "<br/><br/>");
//请求头信息
response.getWriter().println("请求头信息:<br/>");
//获取版本内核
response.getWriter().println("获取版本内核" + request.getHeader("user-agent") + "<br/><br/>");
//请求体信息
response.getWriter().println("请求体信息:<br/>");
response.getWriter().println("用户名:" + request.getParameter("username") + "<br/>");
response.getWriter().println("密码:" + request.getParameter("password") + "<br/>");
response.getWriter().println("姓名:" + request.getParameter("name") + "<br/>");
response.getWriter().println("年龄:" + request.getParameter("age") + "<br/>");
response.getWriter().println("性别:" + (request.getParameter("sex")==(Object)1 ? "男" : "女") + "<br/>");
response.getWriter().println("爱好:");
for (String ele : request.getParameterValues("hobby")) {
response.getWriter().println(ele + "  ");
}
//响应头中定时刷新
response.getWriter().println("<br/><font color=red>10秒后跳转回主界面</font>");
response.setHeader("refresh","10;url=/xjm/index.html");
//设置响应状态码 200 表示正常完成响应
response.setStatus(200);
System.out.println(response.getStatus());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//请求行信息
response.setContentType("text/html;charset=utf-8");
response.getWriter().println("请求行信息:<br/>");
response.getWriter().println("请求的方式:" + request.getMethod() + "<br/>");
response.getWriter().println("请求动态路径:" + request.getContextPath() + "<br/>");
response.getWriter().println("请求的ip:" + request.getRemoteAddr() + "<br/>");
response.getWriter().println("请求的资源:" + request.getRequestURI() + "<br/>");
response.getWriter().println("获取请求的参数:" + URLDecoder.decode(request.getQueryString(),"utf-8") + "<br/>");
response.getWriter().println("获取请求协议和版本:" + request.getProtocol() + "<br/><br/>");
//请求头信息
response.getWriter().println("请求头信息:<br/>");
//获取版本内核
response.getWriter().println("获取版本内核" + request.getHeader("user-agent") + "<br/><br/>");
//请求体信息
response.getWriter().println("请求体信息:<br/>");
response.getWriter().println("用户名:" + new String(request.getParameter("username").getBytes("iso8859-1"), "utf-8") + "<br/>");
response.getWriter().println("密码:" + request.getParameter("password") + "<br/>");
response.getWriter().println("姓名:" + new String(request.getParameter("name").getBytes("iso8859-1"), "utf-8") + "<br/>");
response.getWriter().println("年龄:" + request.getParameter("age") + "<br/>");
response.getWriter().println("性别:" + (request.getParameter("sex")==(Object)1 ? "男" : "女") + "<br/>");
response.getWriter().println("爱好:");
for (String ele : request.getParameterValues("hobby")) {
response.getWriter().println(new String(ele.getBytes("iso8859-1"), "utf-8") + "  ");
}
//响应头中定时刷新
response.getWriter().println("<br/><font color=red>10秒后跳转回主界面</font>");
response.setHeader("refresh","10;url=/xjm/index.html");
//设置响应状态码 200 表示正常完成响应
response.setStatus(200);
System.out.println(response.getStatus());
}
}
ShowServlet.java
package servletContext;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ShowServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建ServletContext对象值
ServletContext sc = getServletContext();
//通过ServletContext获取访问次数
Integer count = (Integer) sc.getAttribute("count");
//判断是否为第一次访问
response.getWriter().println(count == 0 ? "0 time" : count == 1 ? "1 time" : count + "times");
}
}
web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<servlet>
<servlet-name>RequestServlet</servlet-name>
<servlet-class>request.RequestServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>CountServlet</servlet-name>
<servlet-class>servletContext.CountServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>ShowServlet</servlet-name>
<servlet-class>servletContext.ShowServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RequestServlet</servlet-name>
<url-pattern>/request</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>CountServlet</servlet-name>
<url-pattern>/count</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ShowServlet</servlet-name>
<url-pattern>/show</url-pattern>
</servlet-mapping>
</web-app>
index.html运行结果:
get方法结果:
post方法结果:
上下文数据共享结果(访问3次之后):