三、HTTP(超文本传输协议)
传输协议:定义了客户端和服务器端通信时,发送数据的格式
特点:
-
基于TCP/IP的高级协议
-
默认端口号:80
-
基于请求/响应模型的:一次请求对应一次响应
-
无状态的:每次请求之间相互独立,不能交互数据
3.1 请求消息响应
数据格式:请求行、请求头、请求空行、请求体
3.1.1 请求行
请求方式 / 请求rul / 请求协议、版本
GET / login.html / HTTP、1.0
请求方式:
HTTP协议有7种请求方式,常用的有两种
- GET
- 请求参数在请求行中,在url后
- 请求的url长度有限制的
- 不太安全
- POST
- 请求参数在请求体中
- 请求的url长度没有限制的
- 相对安全
3.1.2 请求头
格式:
请求头名称:请求头值
常见的请求头:客户端浏览器告诉服务器一些信息
-
User-Agent:浏览器告诉服务器,我访问你使用的浏览器版本信息
可以在服务器端获取该头的信息,解决浏览器的兼容性问题
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String agent = req.getHeader("user-agent"); if(agent.contains("Chrome")) { System.out.println("我是谷歌"); } else if(agent.contains("Firefox")) { System.out.println("我是火狐"); } }
-
Refere:告诉服务器,我(当前请求)从哪里来?
-
作用:防盗链
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String referer = req.getHeader("referer"); System.out.println(referer); //http://localhost:8080/myweb/login.html //防盗链 if(referer != null) { if(referer.contains("/myweb")) { System.out.println("正常访问,播放电影"); } else { //如果通过其他项目访问就是非法的 //盗链 System.out.println("非法访问,想开电影请去爱奇艺"); } } }
-
统计工作
-
3.1.3 请求空行
空行,就是用于分割POST请求的请求头,和请求体的。
3.1.4 请求体(正文)
作用:封装POST请求消息的请求参数的
GET方式没有请求体,POST方式才有
请求体就是form表单提交的数据
3.2 响应消息数据格式
数据格式:响应行、响应头、响应空行、响应体
3.2.1 响应行
组成:协议/版本 响应状态码 状态码描述
响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态
-
状态码都是3位数字
分类
-
1XX:客户端服务器接受客户端消息,但是没有接受完成,等待一段时间后,发送1XX状态码
-
2XX:成功。代表:200
-
3XX:重定向。代表:302(重定向)、304(访问缓存)
-
重定向
代码实现:@WebServlet("/responseDemo1") public class ResponseDemo1 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("demo1..."); //重定向 response.sendRedirect("/myweb/responseDemo2"); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } } --------------------------------------------------------------------------- @WebServlet("/responseDemo2") public class ResponseDemo2 extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("demo2..."); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request,response); } } --------------------------------------------------------------------------- 访问/myweb/responseDemo1,控制台输出:demo1... demo2...
-
特点
-
地址栏发生变化
-
重定向可以访问其他站点(服务器)的资源
-
重定向是两次请求。不能使用request对象来共享数据
-
-
-
访问缓存
-
-
4XX:客户端错误。代表:
- 404:请求路径没有对应的资源(URL不对)
- 405:请求方式没有对应的doXxx方法
-
5XX:服务器错误。代表:500(服务器内部出现异常)
-
3.2.2 响应头
格式:头名称:值
常见的响应头:
-
Conten-Type:服务器告诉客户端本次响应体数据格式,以及编码格式。(text/html:表示响应体是文本内容并且是html内容)
-
Content-disposition:服务器告诉客户端以什么格式打开响应体数据
值
- in-line:默认值,在当前页面内打开
- attachment:以附件形式打开响应体。比如:文件下载
3.2.3 响应空行
3.2.4 响应体
即:传输的数据
四、Request
4.1 Request和Response对象的原理:
- Request和Response对象是由服务器创建的。我们来使用他们
- Request对象是来获取请求消息,Response对象是来设置响应消息
Request对象继承体系结构
ServletRequest ------ 接口
HttpServletRequest ------ 接口(继承ServletRequest)
org.apache.catalina.connnector.RequestFacade —— 类(Tocat编写的,实现HttpServletRequest )
4.2 Request功能
4.2.1 获取请求消息数据
4.2.1.1 获取请求行数据
-
GET/myweb/demo.do?name=zhangsan HTTP/1.1
-
获取请求方式:GET
String getMethod()
-
获取虚拟目录:/myweb
String getContextPath()
-
获取Servlet路径:/demo.do
String getServletPath()
-
获取get方式请求参数:name=zhangsan
String getQueryString()
-
获取请求URI:/myweb/demo.do
String getRequestURI()
/myweb/demo.doStringBuffer getRequestURL()
http://localhost/myweb/demo.do- URL:统一资源定位符:http://localhost/myweb/demo.do 中华人民共和国
- URI(表示的范围大):统一资源标识符:/myweb/demo.do 共和国
-
获取客户机的IP地址
String getRemoteAddr()
-
4.2.1.2 获取请求头数据
方法:
String getHeader(String name)
:通过请求头的名称获取请求头的值Enumeration<String> getHeaderNames()
:获取所有请求头名称(返回值就类似于一个迭代器)
Enumeration<String> headerNames = req.getHeaderNames();
while (headerNames.hasMoreElements()) {
System.out.println(headerNames.nextElement() +":"+req.getHeader(headerNames.nextElement()));
}
4.2.1.3 获取请求体数据
只有POST请求方式才有请求体,在请求体中封装了POST请求的请求参数
步骤:
- 获取流对象(这个流对象是Tomcat给返回的)
- BufferedReader getReader():获取字符输入流,只能操作字符数据
- ServletInputStream getInputStream():获取字节输入流,可以操作所有类型数据(文件上传)
4.2.2 其他功能
4.2.2.1 获取请求参数通用方式
- ※
String getParameter(String name)
:根据参数名称获取参数值 String[] getParameterValues(String name)
:根据参数名称获取参数值的数组(用于复选框,hobby=study&hobby=game)Enumeration<String> getParameterNames()
:获取所有请求的参数名称- ※
Map<String, String[]> getParameterMap()
:获取所有参数的map集合
中文乱码问题:
- get方式:Tomcat8已经将get方式乱码问题解决了
- post方式会乱码
- 解决:在获取参数前,设置request的编码
request.setCharacterEncoding("utf-8");
- 解决:在获取参数前,设置request的编码
4.2.2.2 请求转发:一种在服务器内部的资源跳转方式(还有一种是重定向,在3.2.1)
步骤
- 通过request对象获取请求转发器对象:getRequestDiapatcher(String path)
- 使用RequestDispatcher对象来进行转发:forward(ServletRequest request, ServletResponse response)
特点:
- 虽然转发了,但是浏览器地址栏路径不发生变化
- 只能转发到当前服务器内部资源中(比如不能转到百度去)
- 转发是一次请求,能使用request对象来共享数据
@WebServlet("/demo2.do")
public class ServletDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo2.do被访问了");
request.getRequestDispatcher("/demo1.do").forward(request,response);
}
-------------------------------------------------------------------------------------
@WebServlet("/demo1.do")
public class RequestDemo extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo1.do被访问了");
}
}
4.2.2.3 共享数据
域对象:一个有范围的对象,可以在范围内共享数据
request域:代表一次请求的范围,一般用于请求转发的多个资源中共享数据
方法:
- void setAttribute(String name, Object obj):存储数据
- Object getAttribute(String name):通过键获取值
- void removeAttribute(String name):通过键移除键值对
4.2.2.4 获取ServletContext
getServletContext()
4.2.2.5
login.html中form表单的 action路径的写法:虚拟目录+Servlet的资源路径
BeanUtils工具类,简化数据封装(用于封装JavaBean)
-
JavaBean:标准的Java类
要求:- 类必须被public修饰
- 必须提供空参的构造器
- 成员变量必须使用private
- 提供公共的setter和getter方法
功能:封装数据
-
概念(之前学的成员变量和属性意思一样,但是这里的含义不一样)
成员变量
属性:
-
setter和getter方法截取后的产物
getUsername() —> Username —> username
-
-
方法
-
setProperty(name, zhangsan):这里的name是属性,而不是成员变量
-
getProperty()
-
pupulate(Object obj, Map map):将map集合的键值对信息,封装到对应的javaBean对象中
五、Response
5.1 Request功能:设置响应消息
设置响应行
格式:HTTP/1.1 200 ok
设置状态码:setStatus(int sc)
设置响应头
setHeader(String name, String value)
设置响应体
使用步骤:
-
获取输出流(这个流对象是Tomcat给返回的)
-
字符输出流:PrintWriter getWriter()(可以写html页面,页面可以自动解析)
注意在获取字符输出流之前一定要写
response.setContentType("text/html;charset=utf-8");
(作用:在获取流对象之前,设置流的默认编码;且告诉浏览器,服务器发送的消息体数据的编码,建议浏览器使用该编码解码) -
字节输出流:ServletOutputStream getOutputStream()
-
-
使用输出流,将数据输出到客户端浏览器
字符流输出:.write(“zaq张澳琪”)
字节流输出:.write(“张澳琪”.getBytes(String charsetName))
六、ServletContext对象
概念:代表整个web应用,可以和程序的容器(服务器)来通信
获取:(两种方式获取的都一样)
-
通过request对象获取
request.getServletContext()
-
通过HttpServlet获取
this.getServletContext()
功能:
-
获取MIME类型:
MIME类型:在互联网通信过程中定义的一种数据类型
- 格式:大类型/小类型 text/html image/jpeg
获取:String getMimeType(String file)
public class Demo extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("demo2..."); //通过HttpServlet获取 ServletContext context = this.getServletContext(); //定义文件名称 String filename = "a.jpg"; //获取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); } }
-
域对象:共享数据
- void setAttribute(String name, Object obj):存储数据
- Object getAttribute(String name):通过键获取值
- void removeAttribute(String name):通过键移除键值对
范围:所有用户所有请求的数据
-
获取文件的真实(服务器)路径
-
String getRealPath(String path)
public class Demo extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //获取文件的服务器路径 String realPath = context.getRealPath("/b.txt"); //web目录下资源访问 String c = context.getRealPath("/WEB-INF/c.txt"); //WEB-INF目录下的资源访问 String a = context.getRealPath("/WEB-INF/a.txt"); //src目录下的资源访问 //这是因为项目中src目录下的文件将来会被部署到web/WEB-INF/classes路径下。 } 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>
</head>
<body>
<a href="/myweb/img/1.jpg">图片1</a>
<hr>
<a href="/myweb/downloadServlet?filename=1.jpg">图片1</a>
</body>
</html>
@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);
}
}
内容持续更新中…