前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >20. Servlet入门 - response介绍以及使用

20. Servlet入门 - response介绍以及使用

作者头像
Devops海洋的渔夫
发布2022-01-14 17:47:19
7410
发布2022-01-14 17:47:19
举报
文章被收录于专栏:Devops专栏

20. Servlet入门 - response介绍以及使用

Response概述

在前面的篇章中我们已经认识了 resquest 请求的相关作用,那么下面来继续认识一下 response 响应。

image-20210108214841273

HttpServletResponse概述

在Servlet API中,定义了一个HttpServletResponse接口(doGet,doPost方法的参数),它继承自ServletResponse接口,专门用来封装HTTP响应消息。由于HTTP响应消息分为响应行、响应头、响应体三部分,因此,在HttpServletResponse接口中定义了向客户端发送响应状态码、响应头、响应体的方法

作用
  • 操作响应的三部分(响应行,响应头,响应体)

小结

  1. Response代表响应对象. 原型是HttpServletResponse, 服务器创建的, 以形参的形式存在doGet()/doPost()方法
  2. Response的作用
    • 操作响应的三部分(行, 头, 体)

Response 设置响应状态码(操作响应行)

当 Servlet 返回响应信息给浏览器的时候,可以设置返回浏览器的响应状态码。

例如:

代码语言:javascript
复制
HTTP/1.1 200

可以使用 setStatus(int sc) 方法来设置响应状态码:

img/

其中常用的状态码:

200:成功

302:重定向

304:访问缓存

404:客户端错误

500:服务器错误

下面我们来写一个Demo来演示一下。

1.创建一个演示的Servlet程序,并设置响应状态码 403

image-20210108220708037

代码语言:javascript
复制
@WebServlet("/ResponseDemo1")
public class ResponseDemo1 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("访问 ResponseDemo1 ....");
        //设置响应状态码: 403 forbidden
        response.setStatus(403);
    }
}

2.在浏览器上测试访问

image-20210108220811810

3. 小结

  1. 设置的API: response.setStatus(int code);
  2. 一般不需要设置, 可能302 重定向需要设置
  3. 常见的响应状态码
    • 200 成功
    • 302 重定向
    • 304 读缓存
    • 404 客户端错误
    • 500 服务器错误

Response 设置 refresh 响应头来进行定时跳转(操作响应头)

上面已经学会了如何使用 Response 来设置响应状态码,那么下面来操作一下响应头。

1.操作响应头的 API 介绍

响应头: 是服务器指示浏览器去做什么

一个key对应一个value

一个key对应多个value

关注的方法: setHeader(String name,String value);

常用的响应头

Refresh:定时跳转 (eg:服务器告诉浏览器5s之后跳转到百度)

Location:重定向地址(eg: 服务器告诉浏览器跳转到xxx)

Content-Disposition: 告诉浏览器下载

Content-Type:设置响应内容的MIME类型(服务器告诉浏览器内容的类型)

下面来演示一下 Refresh 进行定时跳转。

2.创建一个演示的Servlet程序,设置响应头定时跳转

image-20210108223112151

代码语言:javascript
复制
@WebServlet("/ResponseDemo2")
public class ResponseDemo2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //目标: 让浏览器在访问ResponseDemo2后三秒,跳转到百度首页
        System.out.println("ResponseDemo2收到了请求。。。");
        //通过"Refresh"响应头
        response.setHeader("Refresh","3;url=https://www.baidu.com");
    }
}

3.在浏览器上测试访问

image-20210108224213961

等待3秒之后,自动跳转至百度,如下:

image-20210108224233411

Response 发起重定向(操作响应头)

上面我们已经通过设置响应头的方式实现了定时跳转,那么下面我们再来看看重定向。

1. Response 设置Location响应头,来进行重定向跳转(立即跳转)

首先创建一个Servlet程序来演示重定向,如下:

image-20210108225507845

代码语言:javascript
复制
@WebServlet("/ResponseDemo3")
public class ResponseDemo3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("ResponseDemo3收到了一个请求...");
        //目标1:浏览器访问ResponseDemo3,会跳转到百度首页
        //重定向跳转的步骤:1. 设置响应状态码为302  2. 设置响应头Location的值为要跳转到的地址
        response.setStatus(302);
        response.setHeader("Location","https://www.baidu.com");
    }
}

2.浏览器测试访问,发现浏览器成功立即跳转至百度

访问 http://localhost:8080/ResponseDemo3

image-20210108225751120

在这是测试中,我们可以确定重定向可以转发至项目外的资源。那么下面我们来转发至项目内的资源看看。

3.设置重定向至项目内的资源

3.1 在 WEB-INF 下创建一个 index.html

image-20210108230052784

3.2 在Servlet中设置重定向到该 index.html ,如下:

image-20210108231529080

代码语言:javascript
复制
@WebServlet("/ResponseDemo3")
public class ResponseDemo3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("ResponseDemo3收到了一个请求...");
        //目标1:浏览器访问ResponseDemo3,会跳转到百度首页
        //重定向跳转的步骤:1. 设置响应状态码为302  2. 设置响应头Location的值为要跳转到的地址
//        response.setStatus(302);
//        response.setHeader("Location","https://www.baidu.com");

        //目标2:浏览器访问ResponseDemo3,会跳转到本项目的index.html页面
        response.setStatus(302);
        response.setHeader("Location","/index.html"); // 路径设置: /项目部署路径/文件在webapp下的路径
    }
}

使用浏览器访问 http://localhost:8080/ResponseDemo3 如下:

image-20210108231635621

那么能不能访问 WEB-INF 中的资源呢?

3.3 尝试重定向至 WEB-INF 中的资源

image-20210108231939579

可以看到浏览器是无法访问 WEB-INF 下的资源的,也就导致无法重定向到。

3.4 使用 sendRedirect 简写重定向

在上面我们重定向既然设置响应码,还是设置请求头,那么有没有简写的方法呢?当然有,下面来看看。

image-20210108232209845

代码语言:javascript
复制
// 重定向的简写方法
response.sendRedirect("/index.html");

在浏览器测试一下,如下:

image-20210108232249318

可以看到一样可以达到重定向的效果的,那么我们只要记住这种写法就好了。

4.小结

img/

  1. 重定向会导致浏览器进行两次请求
  2. 重定向的地址栏路径改变
  3. 重定向的路径写绝对路径(带域名/ip地址的, 如果是同一个项目里面的,域名/ip地址可以省略)
  4. 重定向的路径可以是项目内部的,也可以是项目以外的(eg:百度)
  5. 重定向不能重定向到WEB-INF下的资源
  6. 把数据存到request里面, 重定向不可用
代码语言:javascript
复制
//方式一: 重定向
//1.设置状态码
//response.setStatus(302);
//2.设置重定向的路径(绝对路径,带域名/ip地址的,如果是同一个项目里面的,域名/ip地址可以省略)
//response.setHeader("Location","https://www.baidu.com");
//response.setHeader("Location","/index.html");

//方式二:  直接调用sendRedirect方法, 内部封装了上面两行
response.sendRedirect("/index.html");
  • 重定向
代码语言:javascript
复制
 response.sendRedirect("重定向的路径");

重定向和请求转发的对比

1. 重定向的特点:

  1. 重定向的跳转是由浏览器发起的,在这个过程中浏览器会发起两次请求
  2. 重定向跳转可以跳转到任意服务器的资源,但是无法跳转到WEB-INF中的资源
  3. 重定向跳转不能和request域对象一起使用
  4. 重定向跳转浏览器的地址栏中的地址会变成跳转到的路径

2. 请求转发的特点:

代码语言:javascript
复制
1. 请求转发的跳转是由服务器发起的,在这个过程中浏览器只会发起一次请求
2. 请求转发只能跳转到本项目的资源,但是可以跳转到WEB-INF中的资源
3. 请求转发可以和request域对象一起使用

使用 Response 的字符输出流向浏览器输出响应体的文本内容(操作响应体)

1.操作响应体的API

页面输出只能使用其中的一个流实现,两个流是互斥的.

一般用法:

  • 如果是输出文本内容到浏览器,那么则需要输出字符到浏览器,用 getWriter()
  • 如果是下载图片等资源,那么则需要输出字节流到浏览器,用getOutputStream()

下面我们首先演示一下输出文本内容的情况。

2.使用 getWriter() 向浏览器输出文本内容

2.1 response.getWriter().writer()方法,只能输出字符串,如果输出int、float等等类型的话,则会有问题

image-20210109085839072

代码语言:javascript
复制
@WebServlet("/ResponseDemo4")
public class ResponseDemo4 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //要向浏览器输出响应体的信息,需要通过流来进行操作
        //第一种:字符串,输出文本内容
        PrintWriter writer = response.getWriter();
        //使用字符流往浏览器输出文本
        //1. writer()方法,只能输出字符串,如果输出int、float等等类型的话,则会有问题
        writer.write("hello world");
    }
}

如果输出 int、float 类型,则会报错如下:

image-20210109085940913

可以看到无法正常显示数字,那么就是需要显示数字呢?这个时候一般就是将其作为字符串输出,如下:

image-20210109090049756

但是如果不想这样,就是向直接输出 int、float 等内容,可以怎么办呢?可以使用 writer.print() 方法。

2.2 response.getWriter().print()方法,可以输出数字、字符串

image-20210109092911409

代码语言:javascript
复制
//2. print()方法,可以输出数字、字符串
writer.print(123456);

可以看到使用 print() 方法的确可以输出数字了,但是我们一般都是只要记住使用 writer() 方法输出字符串即可。

2.3 输出中文字符串,出现乱码问题

上面我们输出英文字符串、数字的情况都是可以的,那么当我们尝试输出中文内容,则会出现乱码,如下:

image-20210109093255116

那么为什么出现乱码呢,当然就是因为编码格式不一致导致的。那么下面我们来看看如何解决乱码问题。

3.中文响应乱码问题的解决

中文乱码的问题是因为服务端的编码格式 与 浏览器的编码格式不一致导致。那么我们只要将其服务端的编码格式设置为 UTF8,然后通知浏览器也设置为 UTF8 编码格式就可以了。

那么如果通知浏览器设置 UTF8 编码格式呢?可以在响应的时候设置如下:

  • 解决字符流输出中文乱码问题
代码语言:javascript
复制
response.setContentType("text/html;charset=utf-8");
/*
 * 这句代码底层做了什么?
 * 1. 设置服务器响应的字符集为UTF-8
 * 2. 设置Content-Type响应头的信息为 "text/html;charset=UTF-8"
 *    让浏览器知道了服务器的响应字符集UTF-8,那么浏览器也会使用UTF-8解码
 */
3.1 解决输出中文乱码问题演示

image-20210109094414469

代码语言:javascript
复制
@WebServlet("/ResponseDemo4")
public class ResponseDemo4 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //解决响应中文乱码
        response.setContentType("text/html;charset=utf-8");

        //要向浏览器输出响应体的信息,需要通过流来进行操作
        //第一种:字符串,输出文本内容
        PrintWriter writer = response.getWriter();
        //使用字符流往浏览器输出文本
        //1. writer()方法,只能输出字符串,如果输出int、float等等类型的话,则会有问题
        writer.write("你好,世界...");

        //2. print()方法,可以输出数字、字符串
//        writer.print(123456);
    }
}
3.2 设置响应编码格式的快捷方式

虽然说解决响应中文乱码就一行代码,但是每次都要去记住还是挺麻烦的。所以我们可以将其设置为一个快捷方式来输入。

File | Settings | Editor | Live Templates

image-20210109094658303

image-20210109094926227

代码语言:javascript
复制
//解决响应中文乱码
response.setContentType("text/html;charset=utf-8");

测试效果如下:

image-20210109094950444

image-20210109095004275

使用 Response 的 字节流 getOutputStream() 向浏览器输出图片内容(操作响应体)

在上面我们已经实现了将字符串内容输出到了浏览器,那么当然我们还要考虑如何将图片内容输出到浏览器。

首先我们来看看默认的DefaultServlet如何处理静态资源。

DefaultServlet 处理静态资源

1.拷贝一张图片到 webapp 目录下

image-20210109101643743

2.启动 tomcat 服务,使用工程路径访问图片资源

image-20210109101820588

那么如果自己写一个Servlet程序,该如何实现这个功能呢?

自己写Servlet,使用 getOutputStream() 将图片资源输出到浏览器

image-20210109102247476

代码语言:javascript
复制
@WebServlet("/ResponseDemo5")
public class ResponseDemo5 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 读取b.jpg图片,将其转换成字节输入流,使用ServletContext
        ServletContext servletContext = getServletContext();
        InputStream is = servletContext.getResourceAsStream("1.jpeg");

        //2. 使用字节输出流,将is中的字节都输出到浏览器
        //2.1 获取响应字节流
        ServletOutputStream os = response.getOutputStream();
        //2.2 读取文件输入流 拷贝到 响应输出字节流
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = is.read(buffer)) != -1){
            os.write(buffer,0,len);
        }

        //3.关闭流
        os.close();
        is.close();
    }
}

在上面的代码中,我们已经实现了图片资源输出浏览器的效果,但是我们可以发现。

当我们每次操作字节流的时候,都要写一串字节流 buffer 拷贝到另一个输出流的操作,比较繁琐:

代码语言:javascript
复制
        //2.2 读取文件输入流 拷贝到 响应输出字节流
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = is.read(buffer)) != -1){
            os.write(buffer,0,len);
        }

有没有比较简便的方法呢?这个当然有,就是可以将其封装为一个公共方法,而这个公共方法已经有第三方提供了,我们可以直接使用。

IO流工具的使用:简化字节流的拷贝操作

  • 引入commons-io的jar包
  • 使用 commons-io 简化字节流的拷贝操作

1.使用 Maven 导入 commons-io的 jar 包依赖

1.1 访问 Maven 仓库,搜索 commons-io 的依赖

访问 https://mvnrepository.com 搜索 commons-io 如下:

image-20210109102853302

image-20210109103030512

image-20210109103057156

代码语言:javascript
复制
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>
1.2 在项目的 pom.xml 导入 commons-io 坐标依赖

image-20210109103247691

代码语言:javascript
复制
<!-- 导入 commons-io       -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>

2.使用 commons-io 中的 IOUtils.copy(is,os); 方法来拷贝流

image-20210109103429361

image-20210109103529178

代码语言:javascript
复制
import org.apache.commons.io.IOUtils;

//2.2 使用 commons-io 中的 IOUtils.copy(is,os); 方法来拷贝流
IOUtils.copy(is, os);

3.查看 IOUtils.copy(is, os) 的源码

image-20210109103717733

image-20210109103730824

可以看到,其实这个 copy 方法也是同样拷贝字节流,只不过封装比较好,方便我们大家的使用。

response的总结

  1. 设置响应状态码:setStatus()
  2. 设置响应头:setHeader(name,value)
    1. refresh响应头,用于隔几秒钟之后跳转到某个页面
    2. location响应头,用于重定向到某个页面
  3. 重定向的写法: sendRedirect(地址)
  4. 设置响应体的内容
    1. response.getOutputStream()获取字节输出流
    2. response.getWriter()获取字符输出流
    3. writer.write()/print()输出字符串
    4. 解决响应数据的中文乱码:response.setContentType("text/html;charset=UTF-8")
    5. 使用字符输出流输出文本内容
    6. 使用字节输出流输出文件
  5. 使用IO流的框架进行边读边写
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-11-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 海洋的渔夫 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 20. Servlet入门 - response介绍以及使用
    • Response概述
      • 小结
    • Response 设置响应状态码(操作响应行)
      • 1.创建一个演示的Servlet程序,并设置响应状态码 403
      • 2.在浏览器上测试访问
      • 3. 小结
    • Response 设置 refresh 响应头来进行定时跳转(操作响应头)
      • 1.操作响应头的 API 介绍
      • 2.创建一个演示的Servlet程序,设置响应头定时跳转
      • 3.在浏览器上测试访问
    • Response 发起重定向(操作响应头)
      • 1. Response 设置Location响应头,来进行重定向跳转(立即跳转)
      • 2.浏览器测试访问,发现浏览器成功立即跳转至百度
      • 3.设置重定向至项目内的资源
      • 4.小结
    • 重定向和请求转发的对比
      • 1. 重定向的特点:
      • 2. 请求转发的特点:
    • 使用 Response 的字符输出流向浏览器输出响应体的文本内容(操作响应体)
      • 1.操作响应体的API
      • 2.使用 getWriter() 向浏览器输出文本内容
      • 3.中文响应乱码问题的解决
    • 使用 Response 的 字节流 getOutputStream() 向浏览器输出图片内容(操作响应体)
      • DefaultServlet 处理静态资源
      • 自己写Servlet,使用 getOutputStream() 将图片资源输出到浏览器
    • IO流工具的使用:简化字节流的拷贝操作
      • 1.使用 Maven 导入 commons-io的 jar 包依赖
      • 2.使用 commons-io 中的 IOUtils.copy(is,os); 方法来拷贝流
      • 3.查看 IOUtils.copy(is, os) 的源码
    • response的总结
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档