HTTP
一、概念:Hyper Text Transfer Protocol 超文本传输协议
二、传输协议:定义了,客户端和服务器端通信时,发送数据的格式
三、特点:
1.基于TCP/IP的高级协议
2.默认端口号:80
3.基于请求 / 响应模型的:一次请求对应一次响应
4.无状态的:每次请求之间相互独立,不能交互数据
四、历史版本:
- 1.0:每一次请求响应都会建立新的连接
- 1.1:复用连接
请求消息数据格式
请求行
一、格式:请求方式 请求url 请求协议/版本
如:GET /login.html HTTP/1.1
二、请求方式:
GET:
1.请求参数在请求行中,在url后
2.请求的uri长度有限制
POST:
1.请求参数在请求体中
2.请求的url长度没有限制
请求头:客户端浏览器告诉服务器一些信息
一、格式:请求头名称:请求头值
二、常见的请求头:
1.User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
可以在服务器端获取该头的 信息,解决浏览器的兼容性问题
2.Referer:http://localhost/login.html
告诉服务器,我(当前请求)从哪里来?
作用:
1.防盗链:
2.统计工作:
请求空行
空行,就是用于,分割POST请求的,请求头和请求体的
请求体(正文)
封装POST请求消息的请求体的
Request:
request对象和response对象的原理
- request和response对象是由服务器创建的。我们来使用它们
- request对象是来获取请求消息,response对象是来设置响应消息
request对象的继承体系结构:
request功能:
一、获取请求消息数据
- 获取请求行数据
请求行:GET /aaa/bbb?name=huhu HTTP/1.1
方法:1.获取请求方式:GET
String getMethod()
2.获取虚拟目录:/aaa
String getContextPath()
3.获取Servlet路径:/bbb
String getServletPath()
4.获取get方式的请求参数:name=huhu
String getQueryString()
5.获取请求的URI: /aaa/bbb
String getRequestURI()
6.获取请求URL:http://localhost/aaa/bbb
StringBuffer getRequestURL()
7.获取协议及版本:HTTP/1.1
String getProtocol()
8.获取客户机的IP地址:
String getRemoteAddr()
package com.hu.web.request;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*
演示Request对象 获取请求行数据
*/
@WebServlet("/RequestDemo1")
public class RequestDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取请求方式:GET
String method = request.getMethod();
System.out.println(method);
//2.获取虚拟目录:
String contextPath = request.getContextPath();
System.out.println(contextPath);
//3.获取Servlet路径:/RequestDemo1
String servletPath = request.getServletPath();
System.out.println(servletPath);
//4.获取get方式的请求参数:name=zhangsan
String queryString = request.getQueryString();
System.out.println(queryString);
//5.获取请求的URI:/RequestDemo1
String requestURI = request.getRequestURI();
System.out.println(requestURI);
//6.获取请求URL:http://localhost:8080/RequestDemo1
StringBuffer requestURL = request.getRequestURL();
System.out.println(requestURL);
//7.获取协议及版本:HTTP/1.1
String protocol = request.getProtocol();
System.out.println(protocol);
//8.获取客户机的IP地址:0:0:0:0:0:0:0:1
String remoteAddr = request.getRemoteAddr();
System.out.println(remoteAddr);
}
}
==URI比URL范围大==
URL:统一资源定位符:http://localhost:8080/RequestDemo1 中华人民共和国
URI:统一资源标识符:/RequestDemo1 共和国
- 获取请求头数据
方法:
String getHeader(String name)
:通过请求头的名称获取请求头的值
Enumeration<String> getHeaderNames()
:获取所有的请求头名称
package com.hu.web.request;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
@WebServlet("/requestDemo2")
public class RequestDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取所有的请求头名称
Enumeration<String> headerNames = request.getHeaderNames();
//2.遍历
while(headerNames.hasMoreElements()){
String name = headerNames.nextElement();
String value = request.getHeader(name);
System.out.println(name+"---"+value);
}
}
}
package com.hu.web.request;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
@WebServlet("/requestDemo3")
public class RequestDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//演示获取请求头:user-agent
String agent = request.getHeader("user-agent");
//判断agent的浏览器版本
if(agent.contains("Chrome")){
//谷歌
System.out.println("谷歌来了....");
}else if(agent.contains("Firefox")){
//火狐
System.out.println("火狐来了....");
}
}
}
package com.hu.web.request;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/requestDemo4")
public class RequestDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//演示获取请求头:referer
String referer = request.getHeader("referer");
System.out.println(referer);//http://localhost:8080/login.html
//防盗链
if(referer!=null){
if(referer.contains("login")){
//正常访问
System.out.println("播放电影...");
}else{
//盗链
System.out.println("请来官网看...");
}
}
}
}
- 获取请求体数据
请求体:只有POST请求方式才有请求体,在请求体中封装了POST请求(封装成流)的请求参数
步骤:
1.获取流对象
BufferedReader getReader()
:获取字符输入流,只能操作字符数据
ServletInputStream getInputStream()
:获取字节输入流,可以操作所有类型的数据
2.再从流对象中拿数据
package com.hu.web.request;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
@WebServlet("/requestDemo5")
public class RequestDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求消息体--请求参数
//1.获取字符流
BufferedReader br = request.getReader();
//2.读取数据
String line=null;
while ((line=br.readLine())!=null){
System.out.println(line);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
二、其他功能
1.获取请求参数通用方式:不论get还是post请求方式都可以使用下面方法来获取请求参数
String getParameter(String name)
:根据参数名称获取参数值
String[] getParameterValues(String name)
:根据参数名称获取参数值的数组
Enumeration<String> getParameterNames()
:获取所有请求的参数名称
Map<String,String[]> getParameterMap()
:获取所有参数的map集合
package com.hu.web.request;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
@WebServlet("/requestDemo6")
public class RequestDemo6 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//post 获取请求参数
//根据参数名称获取参数值
String username = request.getParameter("username");
System.out.println("post");
System.out.println(username);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*//get 获取请求参数
//根据参数名称获取参数值
String username = request.getParameter("username");
System.out.println("get");
System.out.println(username);*/
doPost(request,response);
}
}
package com.hu.web.request;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
@WebServlet("/requestDemo6")
public class RequestDemo6 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//post 获取请求参数
//根据参数名称获取参数值
String username = request.getParameter("username");
//根据参数名称获取参数值的数组
String[] hobbies = request.getParameterValues("hobby");
for (String hobby : hobbies) {
System.out.println(hobby);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
package com.hu.web.request;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
@WebServlet("/requestDemo6")
public class RequestDemo6 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//根据参数名称获取参数值的数组
String[] hobbies = request.getParameterValues("hobby");
for (String hobby : hobbies) {
System.out.println(hobby);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
中文乱码问题:
get方式:tomcat 8 已经将get方式中文乱码解决
post方式:会乱码
解决: 在获取参数前,设置request的编码request.setCharacterEncoding("utf-8");
2.请求转发:一种在服务器内部的资源跳转方式
步骤:
- 通过request对象获取请求转发器对象:
RequestDispatcher getRequestDispatcher (String path)
- 使用RequestDispatcher 对象来进行转发:
forword(ServletRequest request,ServletResponse response)
特点:
- 浏览器地址栏路径不发生变化
- 只能转发到当前服务器内部资源中
- 转发是一次请求
3.共享数据:
域对象:一个有作用范围的对象,可以在范围内共享数据
request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
方法:
void setAttribute(String name,Object obj)
:存储数据Object getAttribute(String name)
:通过键来获取值void removeAttribute(String name)
:通过键来移除键值对
4.获取ServletContext:
ServletContext getServletContext ()
响应消息数据格式
响应字符串格式
响应行
一、组成:
协议/版本 响应状态码 状态码的描述
二、响应状态码:
服务器告诉客户端浏览器本次请求和响应的一个状态 状态码都是三位数字
分类:
1xx:服务器接受客户端消息,但没有接受完成,等待一段时间后,发送1xx的状态码
2xx:成功。代表:200
3xx:重定向.代表302(重定向),304(访问缓存)
4xx:客户端错误。代表404(请求路径没有对应的资源),405(请求方式没有对应的doXxx方法)
5xx:服务器端错误。代表500(服务器内部出现异常)
响应头
一、格式:
1.头名称:值
2.常见的响应头:
- Content-Type:服务器告诉客户端本次响应体的数据格式以及编码格式
- Content-disposition:服务器告诉客户端以什么样的格式打开响应体数据
值:
in-line:默认值,在当前页面内打开
attachment;filename=xxx:以附件形式打开响应体。文件下载
响应空行
空行
响应体
传输的数据
Response
功能:设置响应消息
设置相应行
一、设置状态码:void setStatus(int sc)
设置响应头
一、设置头:void setHeader(String name,String value)
设置响应体
一、使用步骤:
1.获取输出流
字符输出流:PrintWriter getWriter()
字节输出流:ServletOutputStream getOutputStream()
2.使用输出流,将数据输出到客户端浏览器
案例
一、完成重定向
1.重定向:资源跳转的方式
代码实现:
//1.设置状态码为302
response.setStatus(302);
//2.设置响应头location
response.setHeader("location","/responseDemo2");
//简单的重定向方法
response.sendRedirect("/responseDemo2");
2.重定向的特点:
1.地址栏发生变化
2.重定向可以访问其他站点(服务器)的资源
3.重定向是两次请求。不能使用request对象来共享数据
3.转发的特点:
1.转发地址栏路径不变
2.转发只能访问当前服务器下的资源
3.转发是一次请求,可以使用request对象来共享数据
4.路径写法:
规则:判断定义的路径是给谁用的?判断请求将来从哪里发出
- 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
-
- 建议虚拟目录动态获取:request.getContextPath()
- 给服务器使用:不需要加虚拟目录
-
- 转发路径
2.服务器服务器输出字符数据到浏览器
步骤:
1.获取字符输出流
2.输出数据
注意:乱码问题
1.PrintWriter writer = response.getWriter();
获取的流的默认编码是ISO-8859-1
2.设置该流的默认编码response.setCharacterEncoding("GBK");
3.告诉浏览器响应体使用的编码response.setContentType("gbk");
package com.hu.web.response;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/responseDemo3")
public class ResponseDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
因为流是从response中获得的,而不是自己new的所以流的编码
就不是gbk 而是ISO-8859-1(tomcat默认编码)
因为response是tomcat创建的,所以编码就是ISO-8859-1
在获取流之前设置编码为gbk即可解决
*/
response.setCharacterEncoding("GBK");
//告诉浏览器,服务器发送的消息体数据的编码。建议浏览器使用该编码解码
response.setHeader("content-type","text/html;charset=gbk");
//简单的方式,设置编码
response.setContentType("gbk");
//1.获取字符输出流
PrintWriter writer = response.getWriter();
//2.输出数据
writer.write("你好 response");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
3.服务器服务器输出字符数据到浏览器
步骤:
1.获取字节输出流
2.输出数据
4.验证码
本质:图片
目的:防止恶意表单注册
package com.hu.web.servlet;
import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;
@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int width=100;
int height=50;
//1.创建一个对象,在内存中代表一个图片(验证码图片对象)
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//2.美化图片
//2.1填充背景色
Graphics g = image.getGraphics();//画笔对象
g.setColor(Color.PINK);//设置画笔颜色
g.fillRect(0,0,width,height);
//2.2画边框
g.setColor(Color.BLUE);
g.drawRect(0,0,width-1,height-1);
String str="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
//生成随机角标
Random ran=new Random();
for (int i = 1; i <= 4; i++) {
int index = ran.nextInt(str.length());
//获取字符
char ch = str.charAt(index);//随机字符
//2.3写验证码
g.drawString(ch+"",width/5*i,height/2);
}
//2.4画干扰线
g.setColor(Color.GREEN);
//随机生成坐标点
for (int i = 0; i < 10; i++) {
int x1 = ran.nextInt(width);
int x2 = ran.nextInt(width);
int y1 = ran.nextInt(height);
int y2 = ran.nextInt(height);
g.drawLine(x1,y1,x2,y2);
}
//3.将图片输出到页面展示
ImageIO.write(image,"jpg",response.getOutputStream());
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
/*
分析:
点击超链接或者图片,需要换一张
1.给超链接和图片绑定单击事件
2.重新设置图片的src属性
*/
window.onload=function () {
//1.获取图片对象
var img = document.getElementById("checkCode");
//2.绑定单击事件
img.onclick=function () {
//加时间戳
var date=new Date().getTime();
img.src="/checkCodeServlet?"+date;
}
//1.获取图片对象
var link = document.getElementById("change");
//2.绑定单击事件
link.onclick=function () {
//加时间戳
var date=new Date().getTime();
link.href="/check.html?"+date;
}
}
</script>
</head>
<body>
<img id="checkCode" src="/checkCodeServlet" />
<a id="change" href="/check.html" >看不清换一张?</a>
</body>
</html>
ServletContext对象
概念:
代表整个web应用,可以和程序的容器(服务器)来通信
获取:
1.通过request对象获取
request.getServletContext();
2.通过HttpServlet获取
this.getServletContext();
package com.hu.web.servletcontext;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/contextDemo1")
public class ContextDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.通过request对象获取
ServletContext context1 = request.getServletContext();
//2.通过HttpServlet获取
ServletContext context2 = this.getServletContext();
System.out.println(context1);
System.out.println(context2);
System.out.println(context1==context2);//true
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
功能:
1.获取MIME类型:
MIME类型:在互联网通信过程中定义的一种文件数据类型
格式:大类型/小类型 text/html image/jpeg
获取:String getMimeType(String file)
package com.hu.web.servletcontext;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/contextDemo2")
public class ContextDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取ServletContext对象
ServletContext context = this.getServletContext();
//2.定义文件名称
String filename="a.jpg";
//3.获取MIME类型
String mimeType = context.getMimeType(filename);
System.out.println(mimeType);//image/jpeg
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
2.域对象:共享数据
setAttribute(String name,Object value)
getAttribute(String name)
removeAttribute(String name)
ServletContext 对象范围:所有用户所有请求的数据
//1.获取ServletContext对象
ServletContext context = this.getServletContext();
//2.保存数据
context.setAttribute("msg","hahha");
//1.获取ServletContext对象
ServletContext context = this.getServletContext();
//2.获取数据
Object msg = context.getAttribute("msg");
System.out.println(msg);
3.获取文件的真实(服务器)路径
方法:
String getRealPath(String path)
package com.hu.web.servletcontext;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
@WebServlet("/contextDemo5")
public class ContextDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取ServletContext对象
ServletContext context = this.getServletContext();
//2.获取文件的服务器路径
String realPath = context.getRealPath("/b.txt");// /代表web目录下资源
System.out.println(realPath);//D:\ideawork\huhu\out\artifacts\tomcate_demo_an_war_exploded\b.txt
//File file = new File(realPath);
String realPath1 = context.getRealPath("/WEB-INF/c.txt");//WEB-INF目录下的资源访问
System.out.println(realPath1);//D:\ideawork\huhu\out\artifacts\tomcate_demo_an_war_exploded\WEB-INF\c.txt
String realPath2 = context.getRealPath("/WEB-INF/classes/a.txt");// src下的文件 在/WEB-INF/classes这个目录下
System.out.println(realPath2);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
文件下载案例
文件下载需求:
1.页面显示超链接
2.点击超链接后弹出下载提示框
3.完成图片文件下载
package com.hu.web.download;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
@WebServlet("/downLoadServlet")
public class DownLoadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取请求参数,文件名称
String filename = request.getParameter("filename");
//2.使用字节输入流加载文件进内存
//2.1找到文件的服务器路径
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("/img/"+filename);
//2.2用字节流关联
FileInputStream fis=new FileInputStream(realPath);
//3.设置response的响应头
//3.1设置响应头类型:content-type
String mimeType = servletContext.getMimeType(filename);//获取文件的mime类型
response.setHeader("content-type","mimeType");
//3.2设置响应头打开方式:content-disposition
response.setHeader("content-disposition","attachment;filename="+filename);
//4.将输入流的数据写出到输出流中
ServletOutputStream sos = response.getOutputStream();
byte[] buff=new byte[1024*8];
int len =0;
while((len=fis.read(buff))!=-1){
sos.write(buff,0,len);
}
fis.close();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}