response对象
Tomcat收到客户端的http请求,会针对每一次请求,分别创建一个代表请求的request对象、和代表响应的response对象
那么我们获取浏览器提交过来的数据,找request对象即可。response对象代表http响应,那么我们向浏览器输出数据,找response对象即可。
什么是HttpServletResponse对象?
http响应由状态行、实体内容、消息头、一个空行组成。HttpServletResponse对象就封装了http响应的信息。
HttpServletResponse的应用
调用getOutputStream()方法向浏览器输出数据
print
Tomcat使用IOS 8859-1编码对其进行转换,“中国”根本对ISO 8859-1编码不支持。
write
"你好呀我是中国".getBytes()这句代码在转成byte[]数组的时候默认查的是gb2312编码,而"你好呀我是中国"支持gb2312编码,所以可以正常显示出来。
输出utf-8中文字符
getOutputStream().write(getBytes())
- 设置头信息,告诉浏览器我回送的数据编码是utf-8的
response.setHeader("Content-Type", "text/html;charset=UTF-8");
- 使用meta标签模拟http消息头,告诉浏览器回送数据的编码和格式
servletOutputStream.write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'>".getBytes());
getwrite().write()
- 使用getWriter()显示中文数据,只需要一个方法就搞掂了!
response.setContentType("text/html;charset=UTF-8")(设置中文码表和浏览器)把response.setCharacterEncoding("UTF-8")(设置中文码表)的工作也做了
调用getWriter()方法向浏览器输出数据
对于getWriter()方法而言,是Writer的子类,那么只能向浏览器输出字符数据,不能输出二进制数据
实现文件下载
java的文件上传下载都是通过io流来完成的,既然要下载图片,首先要能够读取到它
//获取到资源的路径
String path = this.getServletContext().getRealPath("/download/1.png");
//读取资源
FileInputStream fileInputStream = new FileInputStream(path);
//获取到文件名,路径在电脑上保存是\\形式的。
String fileName = path.substring(path.lastIndexOf("\\") + 1);
告诉浏览器,我要下载这个文件
//设置消息头,告诉浏览器,我要下载1.png这个图片
response.setHeader("Content-Disposition", "attachment; filename="+fileName);
为了解决文件名乱码,我们要进行URL编码,代码如下:
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
将读取到的内容回送给浏览器
//把读取到的资源写给浏览器
int len = 0;
byte[] bytes = new byte[1024];
ServletOutputStream servletOutputStream = response.getOutputStream();
while ((len = fileInputStream.read(bytes)) > 0) {
servletOutputStream.write(bytes, 0, len);
}
//关闭资源
servletOutputStream.close();
fileInputStream.close();
实现自动刷新
让浏览器实现自动刷新,那肯定又是修改消息头了。
//每3秒自动刷新网页一次
response.setHeader("Refresh", "3");
设置缓存
浏览器本身就存在着缓存机制
禁止缓存的功能
//浏览器有三消息头设置缓存,为了兼容性!将三个消息头都设置了
response.setDateHeader("Expires", -1);
response.setHeader("Cache-Control","no-cache");
response.setHeader("Pragma", "no-cache");
实现数据压缩
GZIPOutputStream写数据的时候,是把数据写到ByteArrayOutputStream上的,等会还要把数据取出来,再写给浏览器
//告诉浏览器这是gzip压缩的数据
response.setHeader("Content-Encoding","gzip");
生出随机图片
要生成一张图片,java提供了BufferedImage类供我们使用
//在内存中生成一张图片,宽为80,高为20,类型是RGB
BufferedImage bufferedImage = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);
//获取到这张图片
Graphics graphics = bufferedImage.getGraphics();
//往图片设置颜色和字体
graphics.setColor(Color.BLUE);
graphics.setFont(new Font(null, Font.BOLD, 20));
//往图片上写数据,先写个12345,横坐标是0,纵坐标是20【高度】
graphics.drawString("12345", 0, 20);
把图片写给浏览器,java又提供了图片流【ImageIO】给我们使用
//把图片传进去,类型是jpg,写给浏览器
ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
重定向跳转
//重定向到index.jsp页面
response.sendRedirect("/zhongfucheng/index.jsp");
其实sendRedirect()方法就是对setStatus(302)和setHeader()进行封装,原理就是setStatus()和setHeader()
getWriter和getOutputStream细节
getWriter()和getOutputStream()两个方法不能同时调用。如果同时调用就会出现异常
Servlet程序向ServletOutputStream或PrintWriter对象中写入的数据将被Servlet引擎从response里面获取,Servlet引擎将这些数据当作响应消息的正文,然后再与响应状态行和各响应头组合后输出到客户端。
Servlet的serice()方法结束后【也就是doPost()或者doGet()结束后】,Servlet引擎将检查getWriter或getOutputStream方法返回的输出流对象是否已经调用过close方法,如果没有,Servlet引擎将调用close方法关闭该输出流对象.
request对象
什么是HttpServletRequest
HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,开发人员通过这个对象的方法,可以获得客户这些信息。
HttpServletRequest常用方法
获得客户机【浏览器】信息
getRequestURL方法返回客户端发出请求时的完整URL。
getRequestURI方法返回请求行中的资源名部分。
getQueryString 方法返回请求行中的参数部分。
getPathInfo方法返回请求URL中的额外路径信息。额外路径信息是请求URL中的位于Servlet的路径之后和查询参数之前的内容,它以“/”开头。
getRemoteAddr方法返回发出请求的客户机的IP地址
getRemoteHost方法返回发出请求的客户机的完整主机名
getRemotePort方法返回客户机所使用的网络端口号
getLocalAddr方法返回WEB服务器的IP地址。
getLocalName方法返回WEB服务器的主机名
获得客户机请求头
getHeader方法
getHeaders方法
getHeaderNames方法
获得客户机请求参数(客户端提交的数据)
getParameter方法
getParameterValues(String name)方法
getParameterNames方法
getParameterMap方法
HttpServletRequest应用
防盗链
获取Referer这个消息头,判断Referer是不是从我的首页来的。如果不是从我的首页来的,跳转回我的首页。
String referer=request.getHeader("Referer");
if(referer== null||!referer.contains("http://localhost:8088/firstServlet/NewSvlt")){
response.sendRedirect("/firstServlet/NewSvlt");
return;
表单提交数据【通过post方式提交数据】
request.getParameter()
request.getParameterValues()
get方式提交数据
通过超链接将数据带给浏览器
<a href="/zhongfucheng/Servlet111?username=xxx">使用超链接将数据带给浏览器</a>
sendRedirect()
sendRedirect("servlet的地址?参数名="+参数值&"参数名=" +参数值);
中文乱码问题
首先我们来看一下post方法是怎么进行参数传递的。当我们点击提交按钮的时候,数据封装进了Form Data中,http请求中把实体主体带过去了【传输的数据称之为实体主体】,既然request对象封装了http请求,所以request对象可以解析到发送过来的数据,于是只要把编码设置成UTF-8就可以解决乱码问题了。
而get方式不同,它的数据是从消息行带过去的,没有封装到request对象里面,所以使用request设置编码是无效的。
Tomcat默认的编码是ISO 8859-1,那么get方式由消息体带过去给浏览器的时候肯定是用ISO 8859-1编码了
- 手工转换
- 设置Tomcat
在8080端口的Connector上加入 URIEncoding="utf-8"
,设置Tomcat的访问该端口时的编码为utf-8,从而解决乱码,这种改法是固定使用UTF-8编码的
当然也有另一种改服务器编码的方式。设置Tomcat的访问该端口时的编码为页面的编码 useBodyEncodingForURI="true",这种改法是随着页面的编码而变。
实现转发
request的getRequestDispatcher.forward(request,response)实现转发
(RequestDispatcher还有另外一个方法include(),该方法可以实现包含一般网页的头部和尾部是不需要改变的。如果我们多个地方使用Servlet输出网头和网尾的话,需要把代码重新写一遍。而使用RequestDispatcher的include()方法就可以实现包含网头和网尾的效果了。)
request也可以称之为域对象,只不过ServletContext的域是整个web应用,而request的域仅仅代表一次http请求
请求转发的细节
如果在调用forward方法之前,在Servlet程序中写入的部分内容已经被真正地传送到了客户端,forward方法将抛出IllegalStateException异常。 也就是说:不要在转发之前写数据给浏览器
如果在调用forward方法之前向Servlet引擎的缓冲区中写入了内容,只要写入到缓冲区中的内容还没有被真正输出到客户端,forward方法就可以被正常执行,原来写入到输出缓冲区中的内容将被清空,但是,已写入到HttpServletResponse对象中的响应头字段信息保持有效。
转发和重定向的区别
实际发生位置不同,地址栏不同
转发是发生在服务器的
转发是由服务器进行跳转的,细心的朋友会发现,在转发的时候,浏览器的地址栏是没有发生变化的,在我访问Servlet111的时候,即使跳转到了Servlet222的页面,浏览器的地址还是Servlet111的。也就是说浏览器是不知道该跳转的动作,转发是对浏览器透明的。通过上面的转发时序图我们也可以发现,实现转发只是一次的http请求,一次转发中request和response对象都是同一个。这也解释了,为什么可以使用request作为域对象进行Servlet之间的通讯。
重定向是发生在浏览器的
重定向是由浏览器进行跳转的,进行重定向跳转的时候,浏览器的地址会发生变化的。曾经介绍过:实现重定向的原理是由response的状态码和Location头组合而实现的。这是由浏览器进行的页面跳转实现重定向会发出两个http请求,request域对象是无效的,因为它不是同一个request对象
用法不同
给服务器用的直接从资源名开始写(转发),给浏览器用的要把应用名写上(重定向)
能够去往的URL的范围不一样
转发是服务器跳转只能去往当前web应用的资源
重定向是服务器跳转,可以去往任何的资源
传递数据的类型不同
转发的request对象可以传递各种类型的数据,包括对象
重定向只能传递字符串
跳转的时间不同
转发时:执行到跳转语句时就会立刻跳转
重定向:整个页面执行完之后才执行跳转
转发和重定向使用哪一个?
转发是带着转发前的请求的参数的。重定向是新的请求。
典型的应用场景:
转发: 访问 Servlet 处理业务逻辑,然后 forward 到 jsp 显示处理结果,浏览器里 URL 不变
重定向: 提交表单,处理成功后 redirect 到另一个 jsp,防止表单重复提交,浏览器里 URL 变了