HTTP协议
定义客户端与服务端数据交互规范
特点
-
基于TCP/IP ,是一种安全的协议
-
基于请求与响应模型
-
默认端口号为80
-
无状态的协议,每次数据传输都要建立连接
请求消息
请求行:请求方法/url/协议版本
请求头:K-V键值对
请求体:携带的数据
请求消息
封装到HttpServletRequest对象中
更改请求体编码格式
方法名 | |
---|---|
req.setCharacterEncoding("utf-8"); | 根据name属性值获取对应value |
resp.setCharacterEncoding("utf-8"); | 响应编码格式 |
获取请求体数据(K-V键值对)
方法名 | |
---|---|
req.getParameter(name) | 根据name属性值获取对应value |
req.getParameterValues(name) | 获取多选框的值 |
req.getParameterMap() | 将请求体中所有K-V键值对取出来 |
//只能获取一个值
req.getParameter("hobby");
//获取多选框(同一个name 有多个值)
String[] hobby = req.getParameterValues("hobby");
for (String string : hobby) {
System.out.println(string);
}
//获取所有参数的K-V键值对(不常用)
Map<String, String[]> parameterMap = req.getParameterMap();
Set<Entry<String, String[]>> entrySet = parameterMap.entrySet();
for (Entry<String, String[]> entry : entrySet) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
获取请求行数据
方法名 | 作用 |
---|---|
getMethod() | 获取请求方式 (POST) |
getContextPath() | 获取虚拟路径(/文件夹名) |
getServletPath() | 获取servlet路径(/类名) |
getReuqestURL() | 获取请求路径(http://localhost/文件名/类名) |
获取请求头信息
方法名 | 作用 |
---|---|
getHeader("K") | 通过请求头中name获取对应的值 |
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取请求方式
req.getMethod();
//获取虚拟路径
req.getContextPath();
//获取请求路径
req.getRequestURL();
//获取请求头中信息(Referer 表示请求来自于哪 IP地址+资源)
req.getHeader("Referer");
}
请求转发
实现资源跳转
实现:req.getRequestDispatcher("/test").forward(req,resp);
特点:
-
发生在服务端(浏览器的地址没有变化,网络中请求记录只有1次),本质是一次请求
-
请求转发路径不写虚拟路径(如果路径给客户端用则写虚拟路径,如果给服务端则不写虚拟路径)
转发实现数据共享
转发是一次请求,我们可以将要共享的数据存放在request对象中
//将数据存储request对象中
//将后面需要使用的数据放在requet中
req.setAttribute("name",name);//存储了K-V键值对
//获取request域中数据
req.getAttribute("name");//根据K获取值
数据的响应
数据格式
响应状态行
协议/版本、状态码
常见响应状态码的含义
状态码 | 含义 |
---|---|
1XX | 服务端接收到用户请求,但没有处理完毕 |
2XX | 200:请求成功 |
3XX | 302:重定向、304:缓存 |
4XX | 404:资源未找到、405:请求方式没有对应的方法进行处理(常见servlet中重写方法删除super调用) |
5XX | 500:服务端内部发生错误 |
响应头
K-V键值对
常见的键值对:
content-type:服务端告诉客户端以哪种方式打开响应的数据及其编码
in-line:默认的,浏览器会直接打开当前数据
attachment:以附件的形式打开文件(文件的下载)
响应体
服务端往客户端传输数据(JSON)
操作响应信息
HttpServletResponse
操作响应行(响应状态码)
//设置响应状态码
setStatus(int code)
操作响应头
setHeader(String name,String value)
案例:实现重定向
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//实现重定向(告诉客户端重新请求一个新的资源)
//1.设置状态码(302)
resp.setStatus(302);
//2.打开页面资源
resp.setHeader("location", "http://www.baidu.com");
}
操作响应体(将服务端数据发送给客户端)
//服务端往客户端发送数据
//获取resp对象写入流
//解决字节码乱码问题(以下两个方法一样)
//resp.setHeader("content-type", "text/html;charset=utf-8");
resp.setContentType("text/html;charset=utf-8");
JSON.toJSONString("转为Json字符串");
resp.getWriter().write("<h1>我是标题</h1>");
资源跳转的方式
转发
特点
-
浏览器地址不会发生变化(服务端行为)
-
request对象实现数据的传递(共享、本质是一次请求)
实现:
// “/test”跳转地址
req.getRequestDispatcher("/test").forward(req, resp);
重定向
特点
-
客户端行为,浏览器地址会发生变化
-
多次请求,不是通过request实现资源共享
实现:
// 重定向(客户端)
resp.sendRedirect(req.getContextPath()+"/test");
会话跟踪技术(4种)
作用:数据共享
一次会话:客户端与服务端之间只要客户端与服务端建立连接(客户端给服务端发送了请求并收到了响应,则意味着会话建立;一方断开连接(关闭浏览器,关闭服务器)则会话结束)
一、通过request对象
域:同一次请求中(转发)
基本使用
// 存储一个K-V键值对
req.setAttribute(name,o);
// 通过K获取值
req.getAttribute(name);
二、Cookie
客户端的会话
基本使用
HttpServlet 1
// 创建Cookie对象并Cookie存值
Cookie cookie = new Cookie("stuname", "tom");
// 将Cookie发送给客户端(Cookie的值存在客户端)
resp.addCookie(cookie);
HttpServlet 2
// 以后所有的请求都会着Cookie,在其他资源文件中(Servlet)可以取出值
Cookie[] cookies = req.getCookies();
for (Cookie cookie : cookies) {
System.out.println(cookie.getName());
System.out.println(cookie.getValue());
}
会话时间
默认Cookie的声明周期是一次会话,只在一次会话中可实现数据共享,我们可设置cookie存活时间
// 以秒为单位
cookie.setMaxAge(60*10);
应用场景
特点:存储一些不敏感信息(数据存在客户端,不安全)
三、Session
服务端的会话技术,数据保存在服务端,相对安全。
基本使用
1、存数据
// 获取session对象(tset1)
HttpSession session = req.getSession();
// 在session对象中存值
Student student = new Student("张三",20);
session.setAttribute("stu",student);
// 重定向至新的HttpServlet
resp.sendRedirect("/webTest/test2");
2、取数据
// 获取Session对象(test2)
HttpSession session = req.getSession();
Student student = (Student)session.getAttribute("stu");
应用场景
-
保持登录状态
-
信息共享
-
记录敏感数据(验证码)
四、ServletContext
表示整个项目,实现在整个项目中数据的共享
应用场景
-
统计用户在线人数
-
文件下载
案例
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取servletContext(表示整个项目)
ServletContext servletContext = req.getServletContext();
//获取文件在服务器的路径(文件上传)
System.out.println(sc.getRealPath("/ClassWork/db.properties"));
//将a.txt文件转为字节输入流
InputStream is = servletContext.getResourceAsStream("/file/a.txt");
resp.setHeader("content-disposition", "attachment");
OutputStream os = resp.getOutputStream();
byte [] buffer = new byte[1024];
int length = -1;
while((length=is.read(buffer))!=-1) {
os.write(buffer, 0, length);
}
os.flush();
os.close();
is.close();
}