Servlet(2)Response 响应对象

JavaServlet中的响应处理:设置、通信与重定向
本文详细阐述了在JavaServlet中设置响应数据的流程,包括响应行、响应头和响应体的设置,以及客户端与服务器的通信过程。重点介绍了Response对象的使用、重定向与请求转发的区别,以及如何动态获取虚拟目录以适应Web应用程序部署的变化。

目录

1、设置响应数据的流程

2、客户端与服务器的通信过程

3、Response对象

4、方法

1)设置响应行

2)设置响应头

3)设置响应体

3.1)设置字符数据的响应体

3.2)设置字节数据的响应体

5、重定向(redirect)

6、请求转发与重定向的区别

7、路径里是否需要加虚拟目录

8、动态获取虚拟目录


1、设置响应数据的流程

  1. 业务处理完后,后台就需要给前端返回业务处理的结果,即响应数据
  2. 把响应数据封装到Response对象中
  3. 后台服务器Tomcat会解析Response对象,按照 响应行+响应头+响应体 格式拼接结果
  4. 浏览器最终解析结果,把内容展示在浏览器给用户浏览

2、客户端与服务器的通信过程

当Web服务器收到客户端的HTTP请求时,它会为每一次请求分别创建一个用于代表请求的request对象和一个用于代表响应的response对象。这是Servlet容器(如Tomcat)处理HTTP请求的标准过程。

Request对象封装了客户端发送的所有请求信息,包括请求行(请求方法、请求URI、协议版本)、请求头(如User-Agent、Accept-Language等)以及请求体(如表单数据、JSON数据等)。Servlet可以通过Request对象来获取这些信息,并根据这些信息执行相应的业务逻辑。

Response对象用于构建并发送服务器的响应给客户端。Servlet可以通过Response对象设置响应状态码、设置响应头、输出响应体等。一旦Servlet完成了响应的构建,Response对象会将响应发送回客户端。

这个过程允许Web服务器与客户端进行交互,处理客户端的请求,并返回相应的数据或资源。这也是Servlet技术能够动态生成Web内容的核心机制。

3、Response对象

Response对象是Servlet容器(Tomcat)创建的 HttpServletResponse接口的实例。

当客户端发送HTTP请求到Servlet容器时,容器会:

  1. 解析请求(包括请求行、请求头、请求体等)。
  2. 根据请求的URL和请求方法(GET、POST等)确定要调用的Servlet。
  3. 创建一个HttpServletResponse实例,该实例封装了响应的详细信息(例如状态码、响应头、响应体等)。
  4. 调用Servlet的相应方法(如doGet()doPost()),并将创建的HttpServletResponse实例作为参数传递。

使用Response对象可以设置响应的状态码、添加响应头、写入响应体(即发送给客户端的数据,如 HTML、JSON 等)。

4、方法

Response对象:设置响应消息

1)设置响应行

  • void setStatus(int sc):设置HTTP响应的状态码(如200表示OK,404表示Not Found)

2)设置响应头

  • void setHeader(String name,String value):设置响应头键值对

3)设置响应体

对于响应体,是通过字符、字节输出流的方式往浏览器写。

3.1)设置字符数据的响应体

要想将字符数据写回到浏览器,需要两个步骤:

第一步:通过Response对象获取字符输出流:

  • response.getWriter():返回值为PrintWriter类型的值 writer

第二步:通过字符输出流写数据

  • writer.write(String s)

应用举例:返回字符串 乌托邦

@WebServlet("/resp1")
public class ResponseDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
           //content-type,告诉浏览器返回的数据类型是HTML类型数据,这样浏览器才会解析HTML标签
                              //设置响应的数据格式及数据的编码
        response.setContentType("text/html;charset=utf-8");
        //1. 获取字符输出流
        PrintWriter writer = response.getWriter();
		 writer.write("乌托邦");
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

启动后访问localhost:8080/response-demo/resp1   页面显示 乌托邦

3.2)设置字节数据的响应体

将字节数据写回到浏览器,需要两个步骤:

第一步:通过Response对象获取字节输出流

  • resp.getOutputStream():返回值ServletOutputStream os

第二步:通过字节输出流写数据 有2种方法:

  • 方法一:os.write(字节数据)
  • 方法二:使用工具类IOUtils (更简单易用)

应用举例1:返回一个图片文件到浏览器,使用方法一:

@WebServlet("/resp2")
public class ResponseDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 读取文件
        FileInputStream fis = new FileInputStream("d://a.jpg");
        //2. 获取response字节输出流
        ServletOutputStream os = response.getOutputStream();
        //3. 完成流的copy
        byte[] buff = new byte[1024];
        int len = 0;
        while ((len = fis.read(buff))!= -1){
            os.write(buff,0,len);
        }
        fis.close();
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

启动后访问localhost:8080/response-demo/resp1   页面显示 要返回的图片


应用举例2:返回一个图片文件到浏览器,使用方法二:

pom.xml添加依赖

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>
@WebServlet("/resp2")
public class ResponseDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 读取文件
        FileInputStream fis = new FileInputStream("d://a.jpg");
        //2. 获取response字节输出流
        ServletOutputStream os = response.getOutputStream();
        //3. 完成流的copy
      	IOUtils.copy(fis,os);
        fis.close();
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

启动后访问localhost:8080/response-demo/resp1   页面显示 要返回的图片

5、重定向(redirect)

是一种资源跳转方式:

  1. 浏览器发送请求给服务器,服务器中对应的资源A接收到请求,但资源A现在无法处理该请求,就会给浏览器响应一个302的状态码+location的一个访问资源B的路径;
  2. 浏览器接收到响应状态码为302就会重新发送请求到location对应的访问地址去访问资源B;
  3. 资源B接收到请求后进行处理并最终给浏览器响应结果。

特点:

  • 浏览器地址栏路径发生变化:当进行重定向访问的时候,由于是由浏览器发送的两次请求,所以地址会发生变化。
  • 可以重定向到任何位置的资源(服务内容、外部均可):因为第一次响应结果中包含了浏览器下次要跳转的路径,所以这个路径是可以任意位置资源。
  • 是两次请求,不能在多个资源使用request共享数据:因为浏览器发送了两次请求,是两个不同的request对象,不能通过request对象进行共享数据。

重定向的实现:

  • 第一种方式:使用setStatussetHeader手动实现重定向:
resp.setStatus(302); // 设置HTTP状态码为302,表示临时重定向  
resp.setHeader("Location", "资源B的访问路径"); // 设置Location响应头,指示重定向的目标URL

  • 第二种方式(推荐):使用sendRedirect方法实现重定向,是Servlet API提供的便捷方法来实现重定向,它在内部调用了setStatussetHeader,并可能处理了其他相关的逻辑。
response.sendRedirect("/request-demo/resp2");

应用举例:

需要创建2个servlet:

@WebServlet("/resp1")
public class ResponseDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("这是resp1");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}
@WebServlet("/resp2")
public class ResponseDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("这是resp2");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

重定向:在ResponseDemo1的doGet方法中给前端响应数据

@WebServlet("/resp1")
public class ResponseDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("这是resp1");
        //重定向 方式一
        //1.设置响应状态码 302
        response.setStatus(302);
        //2. 设置响应头 Location
        response.setHeader("Location","/request-demo/resp2");
     //重定向 方式二 
     // resposne.sendRedirect("/request-demo/resp2");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

启动访问 http://localhost:8080/response-demo/resp1  控制台打印:

这是resp1

这是resp2

说明/resp1、/resp2都被访问到了,重定向已经完成了。
 

6、请求转发与重定向的区别

7、路径里是否需要加虚拟目录

浏览器使用:需要加虚拟目录(项目访问路径),

如超链接 <a href='路径'>、form表单 <form action='路径'>、重定向(路径最终是由浏览器发送请求) resp.sendRedirect("路径")。

服务端使用:不需要加虚拟目录,

如请求转发(在服务端进行) req.getRequestDispatcher("路径")。

8、动态获取虚拟目录

推荐动态获取虚拟目录,防止之后用Tomcat插件重新配置项目的访问路径时,需要修改所有重定向的访问地址。

方法:

  • 使用request对象方法:request.getContextPath()
  • 这个方法返回的是当前请求的上下文路径(Context Path)。
  • 上下文路径是部署在 Web 应用程序服务器上的 Web 应用程序的 URL 的一部分。例如,如果 Web 应用程序被部署在 http://example.com/myapp/,那么 myapp 就是上下文路径。
  • request.getContextPath() 通常用于构建相对于上下文路径的资源 URL。

动态获取虚拟目录 修改之后的重定向应用举例:

@WebServlet("/resp1")
public class ResponseDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("resp1....");

        //方式二完成重定向
        //动态获取虚拟目录
        String contextPath = request.getContextPath();
        response.sendRedirect(contextPath+"/resp2");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值