JavaWeb——HttpServletResponse对象详解

212 阅读5分钟

「这是我参与11月更文挑战的第29天,活动详情查看:2021最后一次更文挑战

JavaWeb——HttpServletResponse对象

Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象、和代表响应的response对象。

什么是HttpServletResponse

HttpServletResponse对象代表服务器的响应。这个对象中封装了向客户端发送数据、发送响应头,发送响应状态码的方法。HttpServletResponse是ServletResponse的子接口,功能和方法更加强大。

HttpServletResponse中的方法

根据方法的功能分类:

负责向浏览器发送数据的方法

public PrintWriter getWriter() throws IOException;
public ServletOutputStream getOutputStream() throws IOException;

负责向浏览器发送响应头的方法

public void setCharacterEncoding(String charset);//设置字符编码
public void setContentLength(int len);//设置内容长度
public void setContentLengthLong(long len);//设置内容长度长
public void setContentType(String type);//设置内容类型
public void setDateHeader(String name, long date);//设置日期标题
public void addDateHeader(String name, long date);//添加日期标题
public void setHeader(String name, String value);//设置标题
public void addHeader(String name, String value);//添加标题
public void setIntHeader(String name, int value);//设置Int标头
public void addIntHeader(String name, int value);//添加Int标头

public void setStatus(int sc);//设置状态码

HttpServletResponse的常见应用

1.向浏览器输出消息

  • 使用OutputStream流

    String data = "中国";
    OutputStream outputStream = resp.getOutputStream();//获取OutputStream输出流
    respPrintWriter out = response.getWriter();//获取PrintWriter输出流.
    setHeader("content-type", "text/html;charset=UTF-8");//通过设置响应头控制浏览器以UTF-8的编码显示数据,
    byte[] dataByteArr = data.getBytes("UTF-8");//将字符转换成字节数组,指定以UTF-8编码进行转换
    outputStream.write(dataByteArr);//使用OutputStream流向客户端输出字节数组
    
  • 使用PrintWriter

    resp.setCharacterEncoding("UTF-8");//设置将字符以"UTF-8"编码输出到客户端浏览器
    PrintWriter out = resp.getWriter();//获取PrintWriter输出流
    out.print();
    

2.下载文件

思路:

  1. 要获取下载文件的路径
  2. 下载的文件名
  3. 设置content-disposition响应头控制浏览器能以下载的形式打开文件
  4. 获取下载的输入流
  5. 创建缓冲区buffer
  6. 获取OutputStream
  7. 将FileOutputStream流写入到buffer缓冲区
  8. 使用OutputStream将缓冲区数据输出到客户端

实现类:

package com.cheng.servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;


public class FileServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 要获取下载文件的路径,写死
        String realPath = "D:\\JavaWeb\\maven\\javaweb-01-servlet\\response\\target\\classes\\images\\fu.png";
        System.out.println("下载文件的路径:"+realPath);
        
        //2. 下载的文件名
        String fileName = realPath.substring(realPath.lastIndexOf("\\") + 1);//获得文件名,路径名最后的"\\"的下一个就是文件名
       
        //3. 设置content-disposition响应头控制浏览器能以下载的形式打开文件
        resp.setHeader("content-disposition","attachment; filename="+fileName);
        
        //4. 获取下载的输入流
        FileInputStream in = new FileInputStream(realPath);
        
        //5. 创建缓冲区buffer
        int len = 0;
        byte[] buffer = new byte[1024];
        
        //6. 获取OutputStream
        ServletOutputStream out = resp.getOutputStream();
        
        //7. 将FileOutputStream流写入到buffer缓冲区,使用OutputStream将缓冲区数据输出到客户端
        while((len=in.read(buffer))>0){
            out.write(buffer,0,len);
        }
        //关闭资源
        out.close();
        in.close();
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

注册servlet

 <servlet>
    <servlet-name>filedown</servlet-name>
    <servlet-class>com.cheng.servlet.FileServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>filedown</servlet-name>
    <url-pattern>/down</url-pattern>
  </servlet-mapping>

启动测试:

下载成功

在这里插入图片描述

注意:如果文件名包含中文,要使用URLEncoder.encode方法进行编码(URLEncoder.encode(fileName, "字符编码")),否则会出现文件名乱码。

//例如当文件名为:鹏程.png
//第三步
response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(fileName, "UTF-8"));

3.Response验证码实现

实现一个八位数的验证码,并让它三秒钟刷新一次

package com.cheng.servlet;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

public class ImageServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //让浏览器每3秒自动刷新一次
        resp.setHeader("refresh","3");
        //在内存中创建一张空白的图片                 宽          高                         颜色
        BufferedImage image = new BufferedImage(200,50,BufferedImage.TYPE_INT_RGB);
        //得到这张图片
        Graphics2D g = (Graphics2D) image.getGraphics();//笔
        //设置背景颜色
        g.setColor(Color.white);//设置背景颜色
        g.fillRect(0,0,100,25);//给图片填充
        //给图片写随机数(验证码)
        g.setColor(Color.BLUE);//设置笔的颜色
        g.setFont(new Font(null,Font.BOLD,20));
        g.drawString(makeNum(),0,25);

        //告诉浏览器这个请求用图片的方式打开
        resp.setContentType("image/png");
        //网站存在缓存,我们要不让浏览器缓存
        resp.setDateHeader("expires",-1);
        resp.setHeader("Cache-Control","no-cache");
        resp.setHeader("Pragma","no-cache");
        //把图片写给浏览器 ImageIO类,用于定位图片读和写
        ImageIO.write(image,"png",resp.getOutputStream());

    }
    private String makeNum() {
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        String num = random.nextInt(99999999) + ""; //返回一个大于等于0小于99999999的随机数,加个空字符串变为String类型
        //这里的8-num.length()一定为0,就算不为0,下面也可以用0补足八位数
        for (int i = 0; i < 8 - num.length(); i++) {
            //所以保证了生成的随机数一定是八位数,
            sb.append("0");
        }
        num = sb.toString() + num;//转化为int类型输出
        return num;
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

注册Servlet

<servlet>
    <servlet-name>Imageservlet</servlet-name>
    <servlet-class>com.cheng.servlet.ImageServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>Imageservlet</servlet-name>
    <url-pattern>/image</url-pattern>
  </servlet-mapping>

测试结果:

在这里插入图片描述 在这里插入图片描述

4.实现重定向

重定向(Redirect)

重定向是指当浏览器请求一个URL时,服务器返回一个重定向指令,告诉浏览器地址已经变了,麻烦使用新的URL再重新发送新请求。

在这里插入图片描述

重定向过程:web资源B收到客户端A的请求后,会通知A去访问web资源C,这个过程中URL会发生改变

测试重定向

package com.cheng.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        
        resp.sendRedirect("/p1/down");//本项目的路径和定位的路径
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

分析重定向的原理:

观察浏览器的网络请求,可以看到两次Http请求

在这里插入图片描述

在这里插入图片描述

如果浏览器请求/red路径,RedirectServlet将处理此请求。由于RedirectServlet在内部又发送了重定向响应,因此,浏览器会收到302响应:当浏览器收到302响应后,它会立刻根据Location的指示请求/down路径

//所以 resp.sendRedirect("/p1/down");的原理为
resp.setHeader("Location","/p1/down");
resp.setStatus(302)//这里的302如果改为301就变为永久重定向

重定向分类:

  • 临时重定向302
  • 永久重定向301

区别:如果服务器发送301永久重定向响应,浏览器会缓存/red到/down这个重定向的关联,下次请求/red的时候,浏览器就直接发送/down请求了。

重定向的作用:

重定向的目的是当Web应用升级后,如果请求路径发生了变化,可以将原来的路径重定向到新路径,从而避免浏览器请求原路径找不到资源。

重定向和转发的区别

  • 相同:都会实现页面的跳转
  • 不同:
    • 重定向时,URL地址栏会发生改变
    • 转发时,URL地址栏不会改变