HTTP协议包含请求和响应部分。HttpServletRequest就代表着请求部分,HttpServletResponse就代表着响应部分。
(一)HttpServletResponse详解
(1)中文乱码问题
产生乱码的原因:编码和解码的方式不一致导致产生乱码,英文不存在乱码问题。
解决方法:(1) 更改浏览器的查看编码(不可取)通知浏览器,使用的码表
(2)在响应头部设置编码格式,告诉浏览器用哪种方式来解析
response.setHeader("Content-Type", "text/html;charset=UTF-8");
或者response.setContentType("text/html;charset=UTF-8");
(2)输出随机验证码
//输出随机验证码图片
public class ResponseDemo3 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//通知浏览器不要缓存
response.setHeader("Expires", "-1");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
int width = 120;
int height = 25;
//创建一副内存图像:BufferedImage
BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//得到属于该图片的画笔:Graphics
Graphics g = image.getGraphics();
//画边框
g.setColor(Color.BLUE);
g.drawRect(0, 0, width, height);
//填充背景色
g.setColor(Color.YELLOW);
g.fillRect(1, 1, width-2, height-2);
//画干扰线
g.setColor(Color.GRAY);
Random r = new Random();
for(int i=0;i<10;i++)
g.drawLine(r.nextInt(width), r.nextInt(height), r.nextInt(width), r.nextInt(height));
//随机数字
g.setColor(Color.RED);
g.setFont(new Font("宋体", Font.BOLD|Font.ITALIC, 20));
int x = 23;
for(int i=0;i<4;i++){
g.drawString(r.nextInt(10)+"", x, 20);
x+=20;
}
//输出到浏览器的页面上:ImageIO
ImageIO.write(image, "jpg", response.getOutputStream());
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
(3)控制浏览器对响应数据不要缓存
//通知浏览器不要缓存
response.setHeader("Expires", "-1");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
(4)控制缓存时间
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//缓存1hour
response.setDateHeader("Expires", System.currentTimeMillis()+60*60*1000);
response.getWriter().write("hello");
}
(5)定时刷新
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
test2(response);
}
private void test2(HttpServletResponse response) throws IOException {
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
response.setHeader("Refresh", "2;URL=/day06/index.html");
out.write("登录成功!2秒后将跳转到主页!若没有跳转,请猛点<a href='/day06/index.html'>这里</a>");
}
(6)文件下载(中文文件名的文件下载)
//中文文件下载
private void test2(HttpServletResponse response)
throws FileNotFoundException, IOException {
//得到要下载的文件
ServletContext sc = getServletContext();
String path = sc.getRealPath("/美女.jpg");//得到文件的真实路径。路径必须以"/"开头,"/"就代表者当前应用
//截取文件名 C:\apache-tomcat-6.0.35\webapps\day06\美女.jpg
String filename = path.substring(path.lastIndexOf("\\")+1);
System.out.println(filename);
//构建输入流
InputStream in = new FileInputStream(path);
//通知客户端以下载的方式打开
response.setHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(filename,"UTF-8"));//中文文件名此处要进行URL编码
response.setHeader("Content-Type", "application/octet-stream");
//response.getOutputStream()得到输出流
OutputStream out = response.getOutputStream();
int len = -1;
byte b[] = new byte[1024];
while((len=in.read(b))!=-1){
out.write(b, 0, len);
}
in.close();
out.close();
}
//最简单的文件下载
private void test1(HttpServletResponse response)
throws FileNotFoundException, IOException {
//得到要下载的文件
ServletContext sc = getServletContext();
String path = sc.getRealPath("/f.jpg");//得到文件的真实路径。路径必须以"/"开头,"/"就代表者当前应用
System.out.println(path);
//构建输入流
InputStream in = new FileInputStream(path);
//通知客户端以下载的方式打开
response.setHeader("Content-Disposition", "attachment;filename=f.jpg");
response.setHeader("Content-Type", "application/octet-stream");
//response.getOutputStream()得到输出流
OutputStream out = response.getOutputStream();
int len = -1;
byte b[] = new byte[1024];
while((len=in.read(b))!=-1){
out.write(b, 0, len);
}
in.close();
out.close();
}
(7)请求重定向
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.sendRedirect("/day06/login.html");//作用同上
}
注意:重定向后,第一个请求中response的对象输出的数据将会被清空,不会在客户端显示,会向重定向后的传递request对象和
被清空后的response对象。
(8)HttpServletResponse细节:
字节流和字符流不能同时使用,互斥的。
通过字符流或字节流输出的数据并不是直接打给浏览器的。而是把数据写到response对象的缓存中的。服务器从缓存中取出数据,按照HTTP协议的响应格式输出给浏览器。
如果你调用的response的输出流没有主动关闭,服务器会替你关的。
(二)HttpServletRequest详解
HttpServletRequest代表着客户端的请求。服务器端要获取客户的请求信息只要找这个对象即可,该对象由容器创建。(1)请求转发和包含
1、请求转发(forward):(当前应用内转)
方式一:
ServletContext.getRequestDispatcher(String path):path必须以"/"开头,表示绝对路径
方式二:
ServletRequest.getRequestDispatcher(String path):path如果"/"开头,表示绝对路径;如果不以"/"开头,表示相对路径
2、转发的细节:AServlet(源组件)--->BServlet(目标组件)
**转发前会清空response的正文。
转发页面上只会输出目标组件的输出,源组件的任何页面输出都无效。
原则:转发前,不要刷新或关闭response的输出流。
3、包含(include):RequestDispatcher
AServlet(源组件)--->BServlet(目标组件):AServlet包含BServlet的输出内容,例如下面的两段代码,第一段包含第二段,第一段中响应头的设置无效,将执行第二段对响应头的设置信息,输出的结果为“我爱中国”。
目标组件所有设置的头都无效,正文有效。
//源组件
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println(request.getContextPath());
response.setContentType("text/html;charset=ISO-8859-1);
response.getWriter().print("我爱");
request.getRequestDispatcher("/RequsetServlet04.do").include(request, response);
}
//目标组件
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
response.getWriter().print("中国");
}
(2)各种URL地址的写法
绝对地址:建议使用
绝对路径的写法:假设项目名为firstApp,何时需要加上应用名称"/firstApp"(如果地址给客户端用,要加上。如果给服务器端用,"/"就代表当前应用,即"/firstApp")
<img src="path"/> 要加/firstApp
<link type="text/style" href="path"/> 要加/firstApp
<a href="path"/> 要加/firstApp
<script type="text/javascript" src="path"/> 要加/firstApp
<form action="path"/> 要加/firstApp
getRequestDispatcher(String path): 不要加。"/"就代表了
头:Refresh=2;URL=path 要加/firstApp
ServletContext.getRealPath(String path): 不要加。"/"就代表了
response.sendRedirect(String path): 要加/firstApp
在服务器端获取项目名 》》request.request.getContextPath()