1、浏览器的缓存机制
如果有些数据不经常更新,那么可以设成缓存,可以提高服务器性能。
//浏览器有三消息头设置缓存,为了兼容性!将三个消息头都设置了
response.setDateHeader("Expires", -1);
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma", "no-cache");
//这⾥为了看效果
PrintWriter printWriter = response.getWriter();
printWriter.print("你好啊" + new Date().toString());
2、数据压缩
压缩的原理是什么?我们知道getOutputStream()和getWriter()都是直接把数据输出给浏览器的。现
在我要做的就是让数据不直接输出给浏览器,先让我压缩了,再输出给浏览器。java提供了GZIP压缩类
给我们
//GZIP的构造⽅法需要⼀个OutputStream⼦类对象,究竟哪个对象适合,我们看下write()⽅法
GZIPOutputStream gzipOutputStream = new GZIPOutputStream();
//查看了下API,write()接收的是byte[]类型的。
gzipOutputStream.write();
//既然是byte[]类型,那么我就给他⼀个ByteArrayOutputStream
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(new
ByteArrayOutputStream());
⽽⽤GZIPOutputStream写数据的时候,是把数据写到ByteArrayOutputStream上的,等会还要把
数据取出来,再写给浏览器,于是就不能以匿名内部类的⽅式给GZIPOutputStream,必须把
ByteArrayOutputStream定义出来
//创建GZIPOutputStream对象,给予它ByteArrayOutputStream
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
GZIPOutputStream gzipOutputStream = new
GZIPOutputStream(byteArrayOutputStream);
//GZIP对数据压缩,GZIP写⼊的数据是保存在byteArrayOutputStream上的
gzipOutputStream.write(ss.getBytes());
//gzipOutputStream有缓冲,把缓冲清了,并顺便关闭流
gzipOutputStream.close();
3、重定向
我们设置http消息头就可以实现重定向跳转
//设置状态码是302
response.setStatus(302);
//HttpServletResponse把常⽤的状态码封装成静态常量了,所以我们可以使⽤
SC_MOVED_TEMPORARILY代表着302
response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
//跳转的地址是index.jsp⻚⾯
response.setHeader("Location", "/zhongfucheng/index.jsp");
其实sendRedirect()⽅法就是对setStatus()和setHeader()进⾏封装,原理就是setStatus()和
setHeader()
4、getWriter和getOutputStream细节
- getWriter()和getOutputStream()两个⽅法不能同时调⽤。如果同时调⽤就会出现异常
- Servlet程序向ServletOutputStream或PrintWriter对象中写⼊的数据将被Servlet引擎从
response⾥⾯获取,Servlet引擎将这些数据当作响应消息的正⽂,然后再与响应状态⾏和各响应
头组合后输出到客户端。 - Servlet的serice()⽅法结束后【也就是doPost()或者doGet()结束后】,Servlet引擎将检查
getWriter或getOutputStream⽅法返回的输出流对象是否已经调⽤过close⽅法,如果没有,
Servlet引擎将调⽤close⽅法关闭该输出流对象.
5、中文乱码问题
- post⽅式直接改request对象的编码
- get⽅式需要⼿⼯转换编码
- get⽅式也可以修改Tomcat服务器的编码,不推荐,因为会太依赖服务器了!
- 提交数据能⽤post就⽤post
6、使⽤ServletContext和request实现Servlet之间的通讯,那么我们⽤哪⼀种
⼀般的原则:可以使⽤request就尽可能使⽤request。因为ServletContext代表着整个web应
⽤,使⽤ServletContext会消耗⼤量的资源,⽽request对象会随着请求的结束⽽结束,资源会被回
收。使⽤request域进⾏Servlet之间的通讯在开发中是⾮常频繁的。
使⽤request实现Servlet之间的通讯,Servlet111代码
//以username为关键字存zhongfucheng值
request.setAttribute("username", "zhongfucheng");
//获取到requestDispatcher对象
RequestDispatcher requestDispatcher =
request.getRequestDispatcher("/Servlet222");
//调⽤requestDispatcher对象的forward()实现转发,传⼊request和response⽅法
requestDispatcher.forward(request, response);
Servlet222代码
//获取到存进request对象的值
String userName = (String) request.getAttribute("username");
//在浏览器输出该值
response.getWriter().write("i am :"+userName);
Servlet222成功拿到了request对象在Servlet111存进的数据。
6、转发的时序图
7、请求转发的细节
如果在调⽤forward⽅法之前向Servlet引擎的缓冲区中写⼊了内容,只要写⼊到缓冲区中的内容还没有
被真正输出到客户端,forward⽅法就可以被正常执⾏,原来写⼊到输出缓冲区中的内容将被清空,但
是,已写⼊到HttpServletResponse对象中的响应头字段信息保持有效。
8、转发和重定向使⽤哪⼀个
典型的应⽤场景:
- 转发: 访问 Servlet 处理业务逻辑,然后 forward 到 jsp 显示处理结果,浏览器⾥ URL 不变
- 重定向: 提交表单,处理成功后 redirect 到另⼀个 jsp,防⽌表单重复提交,浏览器⾥ URL 变了