上下文对象-请求对象-响应对象
ServletContext
什么是ServletContext
- ServletContext代表是一个web应用的上下文对象(web应用对象)
- 里面封装的都是web应用信息
- 一个ServletContext对应一个应用
ServletContext的生命周期
- 在服务器一启动的时候就会创建
- 在服务器关闭的时候销毁
如何获得上下文
1.通过init方法当中一个参数ServletConfig来获取
2.直接在HttpServlet当中获取
-
this.getServletContext
-
这种方法本质还是通过config来去获取的
获取全局的初始化参数
- 初始化参数不能再某一个Servlet当中来去配置。在最外层来去配置
- 获取全局初始化参数
获得Web应用中某一个资源的资源的绝对路径
- context.getRealPath("文件")
- 相对的是web应有根目录
context.getRealPath("index.html")
D:JavaTomcatapache-tomcat-7.0.85webappseiindex.html
在你写的名称前面自动拼接上当前工程的绝对地址
ServletContext是一个域对象
什么是域?
- 能够存储数据
域对象
- 能够存取数据流的对象
ServletContext域对象的作用范围
- 整个web应用
- 所有的web资源都可以进行存取数据
- 数据是可以共享的
获取完ServletContext之后向里面写数据
context.setAttribute(String name,Object value);
获取完ServletContext之后,通过name取出存放的数据
context.getAttribute(String name);
获取完ServletContext之后,删除指定名称的值
Context.removeAttribute(String name);
response
response响应过程
- 在去发送一个请求时, 会找到tomcat引擎
- 引擎会找到对应的web应用
- 并且会创建request对象和response对象
- 找到应用后, 会执行应用的web.xml再去根据url-pattern的内容创建Servlet对象
- 并且会调用Servlet对象的service方法,把创建的request对象和response对象传入到方法当中
- 拿到response对象后, 自己可以往响应当中写入一些自己给客户端的内容
- 通过response.getwrite().wirte("写的内容")方法进行写入
- 写的内容,是存到一个response缓冲区当中
- 当方法执行结束之后, tomcat就会从response缓冲区当中取出数据
- 取出你的数据同时,它自己还会自动的往里面添加一些服务器相关的信息进去
- 所以响应给浏览器时, 可以看到除了自己写的内容, 还会有一些服务器相关的信息
流程图
通过response设置响应行,响应头 ,响应体
设置响应行
response.setState(Int code)
设置响应头
add
- add代表添加新的内容
- addHeader(String name,String value)
- addIntHeader(String name,int value)
- addDateHeader(String name,date)
set
- set代表设置,已经存在的内容
- setHeader(String name,String value)
- setIntHeader(String name,int value)
- setDateHeader(String name,Date value)
- 添加两个相同的name
重定向
什么是重定向
- 到服务器当中去找servlet1
- servlet1当中没有这个资源,告诉你去找servlet2
- 再去发送一个请求到servlet2
状态码
302
特点
1.要访问两次服务器
- 第一次访问是人为的去访问
- 第二次是自动的访问
2.浏览器地址栏已经发生变化
设置重定向
-
设置响应码
-
设置响应头
封装的重写向
-
每次都要写状态码,和location比较麻烦
-
就给封装了一个方法 response.sendRedirect("/bei/servlet2")
定时刷新重定向
response.setHeader("refresh","5;url=http://www.baidu.com") -
5代表5秒
-
url的值为5秒后要去跳转的地址
设置响应体
1.通过write方法来写
response.getwrite().wirte(“要写的内容”)
默认情况下写的中文内容会乱码
把写的内容存到缓存区中使用的是ISO8859
ISO8859不支持中文,所以会乱码
在存之前设置可以设置存放的编码
response.setCharacterEncoding("UTF-8")
告知浏览器使用的是utf-8编码
response.setHeader("Content-Type", "text/html;charset=UTF-8");
上面代码只需要写第二句就行, tom看到设置了为utf-8的编码,它在存在的时候也会使用utf-8的编码
使用封装写法
response.setContentType("text/html;charset=UTF-8");
2.通过OutPutStream来写
FileInputSteam
read方法读取一个字节
read(byte[] b)
- 一次读取多个字节,并存放到数组b中
- 上面是一次一滴一滴给你,这种是一次装一水桶再给你
读取全部的数据
FileOutputSteam
write()
一次性写一个字符
write(buffer)
一个性写多个字符
write(buffer,0,len)
一次性写指定个数的字符
response注意点
getWrite()和getOutputSteam不能同时调用
下载功能
下载文件
1.直接使用a标签来去下载,存在的问题
- 有些内容会浏览器自动解析
- 浏览器不能解析的文件才会被下载
2.通过发送Servlet请求来去下载
通过发送一个Servlet请求,把文件名发送给服务器
发送给服务器后,接收到文件名参数,获取文件的绝对地址
通过流的形式来去写到浏览器
还得要告诉文件是什么类型
浏览器是以MIME的类型来识别类型
this.getServletContext().getMimeType(“文件名称”)
设置响应的类型
res.setContentType("MIME类型")
设置响应头,告诉浏览器不要去解析,是以附件的形式打开,
res.setHeader("Content-Dsiposition","attachment;filename="+文件名)
步骤
1.接收文件名参数
2.获取mime类型
3.设置浏览器响应类型
4.告诉浏览器以附件形式下载
5.获取文件的绝对路径
6.读取文件流
7.获取输出流
8.把内容写出到输出流
//1.接收文件名参数
String filename = request.getParameter("filename");
String mime = this.getServletContext().getMimeType(filename);
response.setContentType(mime);
response.setHeader("Content-Disposition", "attachment;filename="+filename);
//2.获取文件的绝对路径
String path = this.getServletContext().getRealPath("download/"+filename);
System.out.println(path);
//3.读取文件流
FileInputStream in = new FileInputStream(path);
//4.获取输出流
ServletOutputStream out = response.getOutputStream();
//5.把内容写出到输出流
byte[] buffer = new byte[1024];
int len = 0;
while((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
解决中文名称乱码问题
获取中文参数报错问题
高版本tomcat中的新特性:就是严格按照 RFC 3986规范进行访问解析,而 RFC 3986规范定义了Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符(RFC3986中指定了以下字符为保留字符:! * ’ ( ) ; : @ & = + $ , / ? # [ ])
.../conf/catalina.properties中,找到最后注释掉的一行 #tomcat.util.http.parser.HttpParser.requestTargetAllow=| ,改成tomcat.util.http.parser.HttpParser.requestTargetAllow=|{},表示把{}放行
1.把获取的字符串参数的字节码获取,再重新使用utf-8编码
2.在设置以附件形式打开时, 不同的浏览器会对默认的名字进行解码
所以根据不同的浏览器,要对名称进行编码之后,再放入文件名
对文件名进行编码
不同的浏览器编码不一样
要先获取agent,取出浏览器的类型
根据不同的浏览器类型进行编码
步骤
1.接收文件名称
2.获取mimeType
3.设置浏览器响应类型
4.先对传入的参数转成二进制流,再使用UTF-8进行编码
5.获取浏览器的信息
6.判断是哪一种浏览器,根据不同的浏览器获取一个编码的文件名
7.设置以附件形式下载,传的名称是编码过的名称
8.获取文件的绝对路径
9.读取文件流
10.获取输出流
11.把文件写到响应当中
// 获取客户端信息
String agent = request.getHeader("User-Agent");
// 定义一个变量记录编码之后的名字
String filenameEncoder = "";
if (agent.contains("MSIE"))
{
// IE编码
filenameEncoder = URLEncoder.encode(filename, "utf-8");
filenameEncoder = filenameEncoder.replace("+", " ");
}
else if (agent.contains("Firefox"))
{
// 火狐编码
BASE64Encoder base64Encoder = new BASE64Encoder();
filenameEncoder = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
}
else
{
// 浏览器编码
filenameEncoder = URLEncoder.encode(filename, "utf-8");
}
注册验证码功能
1.把别人写好的验证码Servlet拿到程序当中
2.编写静态页面
3.编写判断验证码是否正确Servlet
1.设置响应编码
2.从ServletContext当中获取验证码
3.获取传入的请求参数
4.从servletContext当中取出存放的验证码
5.把接收的验证码与取出的验证码时行比较
6.相同时,显示成功
7.不同时, 显示失败,隔3秒钟跳转到输入验证码界面
request
如何获取请求行, 请求头,请求体
获取请求行
获取请求方法
String getMethod()
获取请求资源
String getRequestURL()
String getRequestURI()
获取应用名称
String getContextPath()
获取get查询参数
String getQueryString()
获取请求头
1.获取所有的请求头名称
2.获取指定的头信息
3.打印所有的请求头和请求头内容
referer
告诉服务器我是从哪个页面链接过来的
注意事项
通过以下方式发送请求才会获取
通过以下方式不会有referer
- 从收藏夹链接
- 单击主页或自定义的地址
- 在浏览器中直接输地址
获取请求体
1.获取一个值
req.getParameter("名称")
2.获取多个值
req.getParameterValues("名称")
返回的是一个数组
3.获取所有请求参数名称
req.getParameterNames()
返回的是一个枚举
4.获取所有请求参数
req.getParameterMap()
获取所有请求参数的key-value集合Map<String,String[]>
解决中文乱码问题
什么时候使用get方式与post方式
1.发送的参数不需要写到数据库当中使用get
2.发送的参数需要保存到数据库当中使用post
form一般提交数据的数据为post
造成乱码的原因
发送请求时, 会对参数进行编码,编码使用的是ISO8859-1 不支持中文,所以乱码
通用解决办法
获取对应的参数
通过iso8859-1转回二进制位,再以utf-8的形式转成字符串
存在的问题,每一个参数都必须得要转回二进制位,再转为字符串
request方法解决中文乱码
只适用于post
请求转发
重定向与请求转发的区别
重定向
- 找servlet1,通过设置响应,告诉浏览器, 再让浏览器发送请求到servlet2
- 发两次请求
- 地址栏会发生变化
请求转发
- 请求转发只需要发送一次直接,找servlet1,在servlet1当中直接转发给servlet2,不要再告诉浏览器
- 只发送一次请求
- 浏览器地址栏当中还是servlet1,不会发生变化
实现转发
1.通过请求对象获取一个转发器
- request.getRequestDispatcher(String path)
- 返回一个RequestDispatcher
2.通过转发器进行转发
- 调用转发器的forward方法进行转发
- disp.forward(req,rep)
request域对象
在一次请求过程当中
request是共享的。在一个servlet当中设置的参数,转发到另外一个servlet,取出来的是同一个
生命周期
创建
发送一个请求时创建一个request对象
销毁
请求结束,浏览器给出响应时,销毁
作用范围
一次请求当中
客户端地址与服务器端地址
客户端地址
- 客户端访问服务器使用的地址
- 服务器外部地址
- 在写的时候要写上web应用的名称 /应用名称/资源
服务器地址
- 在服务内部当中使用的地址
- 不需要写web应用名称 /资源名称