0
点赞
收藏
分享

微信扫一扫

Response


文章目录

  • ​​Response设置响应数据​​
  • ​​Response请求重定向​​
  • ​​重定向的特点​​
  • ​​附:路径问题​​
  • ​​Response响应字符数据​​
  • ​​Response响应字节数据​​

Response设置响应数据

Reponse的继承体系和Request的继承体系非常相似:

Response_http


我们使用的也是ResponseFacade实现类,所以用法与前文的Request差不多

Response_ide_02

Response请求重定向

Response重定向(redirect):一种资源跳转方式。

Response_java_03


实现过程:

(1)浏览器发送请求给服务器,服务器中对应的资源A接收到请求

(2)资源A现在无法处理该请求,就会给浏览器响应一个302的状态码+location的一个访问资源B的路径

(3)浏览器接收到响应状态码为302就会重新发送请求到location对应的访问地址去访问资源B

(4)资源B接收到请求后进行处理并最终给浏览器响应结果,这整个过程就叫重定向

实现方式:
①普通方式

resp.setStatus(302);
resp.setHeader("location","资源B的访问路径");

②简便方式

resposne.sendRedirect("资源B的访问路径")

我们还是通过一个例子去理解它:

Response_ide_04

(1)创建ResponseDemo1类

@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);
}
}

(2)创建ResponseDemo2类

@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);
}
}

(3)在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");
}

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

(4)启动测试

访问​​http://localhost:8080/request-demo/resp1​​,就可以在控制台看到如下内容:

resp1...
resp2...

说明​​/resp1​​​和​​/resp2​​都被访问到了。到这重定向就已经完成了。

重定向的特点

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

我们可以看看重定向请求转发的对比:

Response_重定向_05

附:路径问题

问题1:转发的时候路径上没有加​​/request-demo​​而重定向加了,那么到底什么时候需要加,什么时候不需要加呢?

Response_前端_06

其实判断的依据很简单,只需要记住下面的规则即可:

  • 浏览器使用:需要加虚拟目录(项目访问路径)
  • 服务端使用:不需要加虚拟目录

对于转发来说,因为是在服务端进行的,所以不需要加虚拟目录

对于重定向来说,路径最终是由浏览器来发送请求,就需要添加虚拟目录。

掌握了这个规则,我么可以来看几个例子:

  • ​<a href='路劲'>​
  • ​<form action='路径'>​
  • req.getRequestDispatcher(“路径”)
  • resp.sendRedirect(“路径”)

答案:

1.超链接,从浏览器发送,需要加
2.表单,从浏览器发送,需要加
3.转发,是从服务器内部跳转,不需要加
4.重定向,是由浏览器进行跳转,需要加。

2问题2:在重定向的代码中,​​/request-demo​​是固定编码的,如果后期通过Tomcat插件配置了项目的访问路径,那么所有需要重定向的地方都需要重新修改,该如何优化?

Response_重定向_07

答案也比较简单,我们可以在代码中动态去获取项目访问的虚拟目录,具体如何获取,我们可以借助前面咱们所学习的request对象中的getContextPath()方法,修改后的代码如下:

@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);
}
}

重新启动访问测试,功能依然能够实现,此时就可以动态获取项目访问的虚拟路径,从而降低代码的耦合度。

Response响应字符数据

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

  • 通过Response对象获取字符输出流: PrintWriter writer = resp.getWriter();
  • 通过字符输出流写数据: writer.write(“aaa”);

接下来我们通过三个场景去进行实验:
①返回一个简单的字符串​​​aaa​

/** 
* 响应字符数据:设置字符数据的响应体
*/
@WebServlet("/resp3")
public class ResponseDemo3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
//1. 获取字符输出流
PrintWriter writer = response.getWriter();
writer.write("aaa");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}

②返回一串html字符串,并且能被浏览器解析
如果直接写出html是不会被浏览器解析的,此时我们就需要设置响应头中的content-type,使html能被识别

PrintWriter writer = response.getWriter();
//content-type,告诉浏览器返回的数据类型是HTML类型数据,这样浏览器才会解析HTML标签
response.setHeader("content-type","text/html");
writer.write("<h1>aaa</h1>");

③返回一个中文的字符串​​你好​​ 我们要注意乱码的问题,所以在返回中文的时候,要进行字符集的设置

//设置响应的数据格式及数据的编码
response.setContentType("text/html;charset=utf-8");
writer.write("你好");

setContentType方法有多种作用,我们既可以用它来设置请求头中的content-type也可以用它来设置字符集。

注意:一次请求响应结束后,response对象就会被销毁掉,所以不要手动关闭流。

Response响应字节数据

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

  • 通过Response对象获取字节输出流:ServletOutputStream outputStream = resp.getOutputStream();
  • 通过字节输出流写数据: outputStream.write(字节数据);

接下来,我们实现通过一个案例加深理解:

  1. 返回一个图片文件到浏览器

/**
* 响应字节数据:设置字节数据的响应体
*/
@WebServlet("/resp4")
public class ResponseDemo4 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);
}
}

上述代码中,对于流的copy的代码还是比较复杂的,所以我们可以使用别人提供好的方法来简化代码的开发,具体的步骤是:

(1)pom.xml添加依赖

<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>

(2)调用工具类方法

//fis:输入流
//os:输出流
IOUtils.copy(fis,os);

优化后的代码:

/**
* 响应字节数据:设置字节数据的响应体
*/
@WebServlet("/resp4")
public class ResponseDemo4 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);
}
}


举报

相关推荐

0 条评论