HTTP响应协议: 响应消息
- 请求消息: 客户端发送给服务器端的数据.
- 数据格式:
- 请求行: 请求方式 url信息 请求协议/版本号.
- 请求头
- 请求空行
- 请求体: 针对post请求方式的,get请求方式没有请求体.
- 数据格式:
- 响应消息: 服务器端发送给客户端的数据.
- 数据格式
- 响应空行
- 响应头
- 响应行
- 响应体: 真实传输的数据,也就是我们传输的html这些文本文件,图片,音频等,这些浏览器都会解析出来.
- 响应字符串的格式
HTTP/1.1 200 OK Bdpagetype: 1 Bdqid: 0xeaa47fdd0001895f Cache-Control: private Connection: Keep-Alive Content-Encoding: gzip Content-Type: text/html;charset=utf-8 Cxy_all: baidu+42cf0987fef07e22ea09fde2f722a2b8 Date: Sun, 12 May 2019 00:31:06 GMT Expires: Sun, 12 May 2019 00:31:06 GMT Server: BWS/1.1 Set-Cookie: delPer=0; path=/; domain=.baidu.com Set-Cookie: BDSVRTM=13; path=/ Set-Cookie: BD_HOME=0; path=/ Set-Cookie: H_PS_PSSID=28883_1449_28981_21108_28518_28775_28721_28964_28830_28585_22160; path=/; domain=.baidu.com Strict-Transport-Security: max-age=172800 Vary: Accept-Encoding X-Ua-Compatible: IE=Edge,chrome=1 Transfer-Encoding: chunked 空行 写响应体,即页面展示的html内容.
- 响应行
- 组成: 请求协议/版本号 http响应状态码 状态码描述,如:
HTTP/1.1 200 OK
. - 响应状态码(
都是三位数字
): 服务器告诉客户端浏览器本次请求和响应的状态,其大概分类有五种.1xx
: 可以理解为客户端给服务器发送消息,服务器只接收到了一半就没有数据了,然后服务器就在那里等着,等待一段时间后,就向客户端发送1xx
的状态码,问客户端你到底还有没有东西这样子, 这个出现不多.2xx
: 表示本次请求和响应成功.代表状态码:200.3xx
: 表示重定向,就是说客户端浏览器访问到了服务器,说我要干这个事,这个servlet说,我干不了,但是我知道servlet2可以干,它就给浏览器返回一个响应说我干不了,同时给浏览器了一个小纸条,让它去找servlet2.- 例如:
302(重定向)
,和request通过forward方法请求装发类似,都是敲一次回车,访问两个地方,不过这个是客户端去访问,而不是和forward方法一样服务器内部跳转. - 例如:
304缓存
,这么理解吧,就是客户端向服务器请求图片这些二进制数据,只能用字节流,每次请求都要从服务器下载就会很慢,它就想了个办法,当客户端第一次请求时候,就把这张图片缓存到浏览器客户端本地,下次客户端访问同一图片(图片未更改)时,服务器就返回304状态码,让客户端去自己本地找就好了.
- 例如:
4xx
: 客户端错误- 代表状态码:
404
,表示浏览器所请求的url路径在服务器中没有对应的资源,一般都是由于浏览器url写错了或者servlet中资源路径错了的原因.405
,表示请求方式没有对应的doxxx方法对应响应,例如,我们在浏览器直接输入url地址时都是通过get方法访问的,但是我们不小心在servlet中把doget()方法删除了,就会出现这个状态码.
- 代表状态码:
5xx
: 服务器端错误,代表服务器内部出现异常了,代表状态码500
,例如,我在dopost()方法中写了一个语句int i = 5/0
,这个会抛出下标不能为0异常,此时我们在浏览器通过url访问该servlet路径,就会报错500
.
- 组成: 请求协议/版本号 http响应状态码 状态码描述,如:
- 响应头:
- 格式: 头名称: 值,和请求头一样,也是键值对.
- 常见的响应头
- Content-Type: 服务器告诉客户端本次响应体数据格式以及编码格式,然后浏览器改变接收编码格式等保证接收正常不出现乱码,例如:
Content-Type: text/html(表示文本格式);charset=utf-8
. - Content-disposition: 服务器告诉客户端以什么格式打开我的响应体数据.
- 默认值: in-line,表示在当前页面内打开.
- attachment;filename=xxx: 以附件形式打开响应体,比如说我们点一个超链接,它不会直接跳转到另一个页面,它会直接下载一个文件.
- Content-Type: 服务器告诉客户端本次响应体数据格式以及编码格式,然后浏览器改变接收编码格式等保证接收正常不出现乱码,例如:
- 数据格式
Response
-
功能: 设置响应消息
- 设置响应行.
- 格式: 例如:
HTTP/1.1 200 OK
. - 设置状态码: setStatus(int sc).
- 格式: 例如:
- 设置响应头.
- 方法: setHeader(String name ,String value).
- 设置响应体.
- 使用步骤:
- 获取输出流
- 字符输出流:
ServletOutputStream getOutputStream()
. - 字节输出流:
PrintWriter getWriter()
.
- 字符输出流:
- 使用输出流,将数据输出到客户端浏览器中
- 获取输出流
- 使用步骤:
- 案例(代码):
- 重定向: 也是资源转发的方式. 完成重定向代码.
- 服务器输出字符数据到浏览器代码.
- 服务器输出字符数据到浏览器代码.
- 设置响应行.
-
几个注意的点:
-
重定向的特点
- 转发特点
- 转发后浏览器地址栏路径不变.
- 转发只能访问当前服务器下的资源,就是同一个src下的资源.
- 转发是一次请求,两次跳转,不过是只按一次回车就可以了,可以通过request对象来共享数据.
- 重定向特点
- 重定向后地址栏发生变化,request的forword()方法跳转到另一个servlet,浏览器中url路径是不会变的,是跳转前的一个servlet路径;而response的重定向,浏览器中的url路径会直接变成最终的servlet路径…
- 重定向可以访问到其它地方(服务器)的资源,就是在idea中不是一个项目中的资源,但是这个项目要部署到tomcat中哈,不然不知道虚拟路径的,以idea为例
- 首先两个项目都要加载到服务器
. - 然后在servlet中调用sendRediect(string url)方法跳转到目标servlet中就可以了,但是这里注意
url必须是**/虚拟路径/资源路径**
.
.
- 首先两个项目都要加载到服务器
- 当然也可以重定向到其它网站中去,例如:
response.sendRedirect("https://www.baidu.com");
,运行后就会直接跳转到百度页面去了,而request请求转发也是不可以的. - 重定向是两次请求,访问两个页面,不过也是只敲一次回车,这个可以在浏览器中通过快捷键
F12
,然后在网络
中查看到变化,这里我就不多赘述了哈,同时这里就不能用request对象来共享数据了.
- 转发特点
-
路径写法
- 路径的分类
- 相对路径(不推荐使用): 通过相对路径不可以确定唯一资源,如:
./index.html
,表示当前目录
下,有一个index.html页面,你可以认为它不以/
开头,以.
开头.- 规则: 要使用相对路径,就必须先找到当前资源和目标资源之间的相对位置关系.
./xx
,代表当前目录.../xx
,代表后退一级目录.
- 绝对路径: 通过绝对路径可以确定唯一资源,如:
http://localhost:8080/response/ResponseDemo1
, 其也可以简化写成/response/ResponseDemo1
,我们 可以认为以/
开头的路径是绝对路径.- 规则: 判断定义的路径是给谁用的, 通过这个请求将来从哪儿发出,从服务器发出就是给服务器使用的,从浏览器页面发出就是给客户端浏览器用的.
- 给客户端浏览器使用: 需要加虚拟目录,我们建议对虚拟目录动态获取.
- 给服务器使用: 不需要加虚拟目录.
- 规则: 判断定义的路径是给谁用的, 通过这个请求将来从哪儿发出,从服务器发出就是给服务器使用的,从浏览器页面发出就是给客户端浏览器用的.
- 基本上哈,就是除了
@WebServlet(urlPatterns="/xx")
中的url和request的请求转发中的路径为资源路径以外,其它所有地方填的url路径都是**/虚拟路径/资源路径**这个格式,例如重定向的时候(这个是从浏览器发出去的要注意啊
),form表单中等. - 还有一个要注意的点,就是重定向的到其它项目的时候,那个url也要带虚拟路径,这个其实就理解为是从浏览器发出的数据就完事了.
- 例子: 相对绝对路径举例.
- 相对路径(不推荐使用): 通过相对路径不可以确定唯一资源,如:
- 注意
- 由于虚拟目录可能随时都需要改变,所以虚拟目录不能一次写死,要动态获取,这里就需要用到request对象中的
String getContextPath()
方法,当然这个只能用在类方法里面哈,html里面用不了的. - 举例:
String contextPath = request.getContextPath(); response.sendRedirect(contextPath+"/responseDemo2");
- 所以说,你要是还不知道虚拟目录是啥,你就打印一些context再去tomcat->编辑结构下面找一下就晓得了.
- 由于虚拟目录可能随时都需要改变,所以虚拟目录不能一次写死,要动态获取,这里就需要用到request对象中的
- 路径的分类
-
重定向方式:
- 告诉浏览器要重定向,通过setStatus()设置状态码302实现;然后告诉浏览器重定向servlet的路径,通过setHeader()方法设置响应头location:告诉浏览器重定向servlet的资源路径实现
- 这也是最常用的方法
重点掌握
: 通过**sendRedirect(String url)**实现,其中url表示重定向资源路径,格式和form表单中action的路径一致,都是/虚拟路径/资源路径
,这两个东西不清楚就去看Request博客下request案例第5点的注意事项
.
-
服务器输出字符数据到浏览器
- 步骤:
- 获取字符输出流.
- 输出数据.
- 产生乱码
- 乱码原因: 编码和解码使用的码表,即字符集不一致
- 浏览器使用的字符集可以通过IE浏览器点击右键查看编码知道,我电脑是
Unicode编码
. - 而服务端的编码表由于是response调方法产生的,不是new出来的(new出来的那就和系统保持一致),而response对象又是tomcat产生的,tomcat又不是中国人写的,所以用的字符集不是Unicode,一般来说是ISO-8859-1的拉丁编码.
- 浏览器使用的字符集可以通过IE浏览器点击右键查看编码知道,我电脑是
- 乱码解决办法: 在获取流之前,设置流的编码,通过一条语句设置:
response.setContentType("text/html;charset=utf-8");
,通过这句话可以告诉浏览器我的响应信息是文本类型的同时字符集是utf-8类型的.
- 乱码原因: 编码和解码使用的码表,即字符集不一致
- 步骤:
-
服务器输出字节数据到浏览器
- 步骤:
- 获取字节输出流.
- 输出数据.
注意: 这里为了防止出现乱码,在用response对象设置编码前,把request的编码设置为相同,同时设置字节流输出时byte数组的编码
- 步骤:
-
案例: 简单的验证码
-
ServletContext(接口)
- 概念: 代表整个web应用,即整个web工程,可以和程序容器(服务器)例如tomcat进行通信.
- 功能:
- 获取MIME类型:
- MIME类型: 在互联网通信过程中定义的一种文件数据类型.
- 格式: 大类型/小类型, 例如: text/html,表示纯文本/html类型.
- 方法: String getMimeType(String file);
- 获取MIME类型案例代码.
- 域对象: 域对象主要是用来共享数据的,如request对象通过调用getAttribute()来共享数据.
- 域对象都有的几个方法:
- void setAttribute(String name, Object value)给name赋值;
- Object getAttribute(String name)通过名称获取值;
- void removeAttribute(String name);
- servletContext范围: 能共享所有用户所有请求的数据,就是只要你是在这个服务器运行的,在哪里运行都可以获取到,而且只要存储数据的类运行一次,它就会一直存在知道类被销毁.
- 共享数据示例代码_设置数据代码.
- 共享数据示例代码_获取数据代码.
- 域对象都有的几个方法:
- 获取文件的真实路径(服务器路径).
- 方法: String getRealPath(String path);
- 获取文件的服务器路径代码.
- 获取MIME类型:
- 获取ServletContext对象
- 通过request对象获取:
request.getServletContext()
. - 通过HttpServlet类获取: 这是该类的父类
GenericServlet
中的一个方法,由于我们的servlet都是继承子httpServlet,所以通过httpservlet获取也行,反正子类具有父类属性,即:this.getServletContext()
.
- 通过request对象获取:
文件下载案例
用谷歌浏览器会直接下载,没有提示框,建议用ie
-
需求:
- 页面显示超链接
- 点击超链接后弹出下载提示框
- 完成图片文件下载
-
分析:
- 超链接指向的资源(比如图片)如果能够被浏览器解析,则该资源会在浏览器中展示,如果不能解析(比如视频),才会弹出下载提示框,这是不满足需求的.我们的需求应该是任何时候都要弹出提示框,这就需要
response
的响应头Content-disposition
了. - 使用响应头来设置资源的打开方式为附件形式:
Content-disposition: attachment;filename=xxx
.
- 超链接指向的资源(比如图片)如果能够被浏览器解析,则该资源会在浏览器中展示,如果不能解析(比如视频),才会弹出下载提示框,这是不满足需求的.我们的需求应该是任何时候都要弹出提示框,这就需要
-
步骤:
- 定义页面,编辑器超链接属性,让其指向servlet,但是这里就需要想到,我们有多个文件,每次弹出的提示框是不一样的,但是指向的都是同一个servlet,这时我们就需要在超链接中用到响应头
Content-disposition
中的filename=xxx
来设置参数了!!! - 定义servlet
- 获取文件的名称.
- 使用字节输入流加载文件进内存.
- 指定response的响应头
Content-disposition
. - 将数据写出到response的输出流即可.
- 定义页面,编辑器超链接属性,让其指向servlet,但是这里就需要想到,我们有多个文件,每次弹出的提示框是不一样的,但是指向的都是同一个servlet,这时我们就需要在超链接中用到响应头
-
案例代码.
-
问题:
- 中文文件名问题(注意这个是不能用response.setContentType解决的),比如我的图片名字是
哆啦A梦.jpg
,在谷歌浏览器里面,它依旧会下载,但是下载名是空白或者下划线,那当然下载下来的东西自然也是看不了的;在ie里面直接会报错400.- 解决思路:
- 获取客户端使用的浏览器版本信息.
- 根据不同的版本信息响应不同的数据,即设置filaname的编码方式不同,这里需要用到一个工具类.
- 解决思路:
- 中文文件名问题(注意这个是不能用response.setContentType解决的),比如我的图片名字是
今天用git推送资源的时候报了个错: unable to access 'https://github.com/fanfan999/WebCodes.git/': SSL certificate problem: self signed certificate
,百度了一下,解决方案是: 输入这行命令 git config --global http.sslVerify false
就可以了.