探索Android软键盘的疑难杂症
深入探讨Android异步精髓Handler
详解Android主流框架不可或缺的基石
站在源码的肩膀上全解Scroller工作机制
Android多分辨率适配框架(1)— 核心基础
Android多分辨率适配框架(2)— 原理剖析
Android多分辨率适配框架(3)— 使用指南
自定义View系列教程00–推翻自己和过往,重学自定义View
自定义View系列教程01–常用工具介绍
自定义View系列教程02–onMeasure源码详尽分析
自定义View系列教程03–onLayout源码详尽分析
自定义View系列教程04–Draw源码分析及其实践
自定义View系列教程05–示例分析
自定义View系列教程06–详解View的Touch事件处理
自定义View系列教程07–详解ViewGroup分发Touch事件
自定义View系列教程08–滑动冲突的产生及其处理
版权声明
- 本文原创作者:谷哥的小弟
- 作者博客地址:http://blog.csdn.net/lfdfhl
在前几篇博客中我们已经对Tomcat,Http,Servlet等方面有了简单的接触,在此基础上我们来深入学习Servlet的响应即HttpServletResponse.
Request、Response简介
Web服务器接收到客户端的http请求后会针对每一次请求创建用于代表请求的request对象以及代表响应的response对象。故,若要获取客户机提交的数据,只需要处理request对象就行;若要向客户端输出数据,只需要处理response对象即可。
HttpServletResponse的简单使用
在此以HttpSerlet为例,介绍HttpServletResponse的使用方式,请看如下示例:
/**
* 本文作者:谷哥的小弟
* 博客地址:http://blog.csdn.net/lfdfhl
*/
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("GBK");
response.setContentType("text/html;chartset=GBK");
PrintWriter writer = response.getWriter();
writer.write("佐佐木希写真全集");
response.addHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Expires", "0");
response.setHeader("refresh", "10;url=http://blog.csdn.net/lfdfhl");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
}
在这段代码中对Get请求做出响应,代码解析如下:
- 设置将发送到客户端的响应内容的字符编码,请参见代码第9行
在此将字符编码设置为GBK - 设置将发送到客户端的响应内容的类型,请参见代码第10行
在此将内容的类型设置为text/html;chartset=GBK - 设置客户端不缓存,请参见代码第13-15行
- 设置客户端在几秒钟后自动跳转,请参见代码第16行
亦可利用response.setContentType()设定发送到客户端的响应内容的类型,即:
response.setContentType(“text/html;chartset=GBK”);
与此类似,也可设置重定向
response.setStatus(302); response.setHeader(“location”,”http://blog.csdn.net/lfdfhl“);
或者利用response.sendRedirect( )设置重定向
response.sendRedirect(“http://blog.csdn.net/lfdfhl“);
同理,我们可用ServletOutputStream向客户端返回字节流
response.setCharacterEncoding("GBK");
response.setContentType("text/html;chartset=GBK");
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write("大泽玛利亚摄影写真".getBytes("GBK"));
HttpServletResponse返回下载文件
刚才的示例中,我们只是返回了简单的文字,现在我们来返回一张照片给客户端,请看如下示例:
/**
* 本文作者:谷哥的小弟
* 博客地址:http://blog.csdn.net/lfdfhl
*/
package cn.com;
import java.io.FileInputStream;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestResponsePhoto extends HttpServlet{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String path=getServletContext().getRealPath("/WEB-INF/ZXM.jpg");
FileInputStream fileInputStream = new FileInputStream(path);
ServletOutputStream outputStream = response.getOutputStream();
int len=0;
byte [] b=new byte[1024];
while((len=fileInputStream.read(b))!=-1){
outputStream.write(b, 0, len);
}
outputStream.close();
fileInputStream.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
}
}
代码解析如下:
- 得到文件路径,请参见代码第20行
- 得到文件输入流,请参见代码第21行
- 从response中获取到ServletOutputStream作为输出流,请参见代码第22行
- 将图片返回给客户端,请参见代码第23-29行
运行后,效果如下图所示:
嗯哼,看到了吧:浏览器中显示了从服务端获取的我女朋友的照片
但是,如果想让用户下载这张照片该怎么办呢?请看如下示例:
/**
* 本文作者:谷哥的小弟
* 博客地址:http://blog.csdn.net/lfdfhl
*/
package cn.com;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DownPhoto extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String path=getServletContext().getRealPath("/WEB-INF/zxm.jpg");
System.out.println("-----------------> path="+path);
String fileName=path.substring(path.lastIndexOf("\\")+1);
fileName=URLEncoder.encode(fileName, "UTF-8");
response.setHeader("content-disposition", "attachment;filename="+fileName);
response.setHeader("content-type", "image/jpeg");
FileInputStream fileInputStream = new FileInputStream(path);
ServletOutputStream outputStream = response.getOutputStream();
int len=0;
byte [] b=new byte[1024];
while((len=fileInputStream.read(b))!=-1){
outputStream.write(b, 0, len);
}
outputStream.close();
fileInputStream.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
super.doPost(req, resp);
}
}
代码解析如下:
- 获取到文件名称,请参见代码第23行
- 设置Header指示客户端下载文件,请参见代码第24行
- 利用Header设置响应的内容的类型
嗯哼,待用户输入地址后即可下载对应的文件。
除此以外,我们可利用画笔在内存中创作一张图片BufferedImage然后再返回给客户端;有的网站登录时的验证码正是采用该方式实现的。
HttpServletResponse的几个细节问题
getOutputStream()和getWriter()分别用于得到输出字节流和输出字符流的ServletOuputStream、Printwriter。但是请注意:getOutputStream()和getWriter()这两个方法互相排斥,调用了其中任意一个方法后就不能再调用另一方法;否则系统抛出异常。
在Servlet中向ServletOutputStream对象或PrintWriter对象写入的数据将被Servlet引擎(如Tomcat)从response里面获取,然后Servlet引擎再将这些数据当作响应消息的正文且与响应状态行和响应头组合并输出到客户端。这也就是说:并不是response将响应消息传递给了客户端,而是Servlet引擎将响应消息封装到了response中再由Servlet引擎传递给客户端
Serlvet的service()结束后,Servlet引擎将检查getWriter()或getOutputStream()返回的输出流对象是否已经调用过close();如果未关闭则Servlet引擎将调用close()关闭该流对象,如果已经关闭则不作处理