Request和Response

==Request是请求对象,Response是响应对象

  • request:==获取==请求数据

    • 浏览器会发送HTTP请求到后台服务器[Tomcat]

    • HTTP的请求中会包含很多请求数据[请求行+请求头+请求体]

    • 后台服务器[Tomcat]会对HTTP请求中的数据进行解析并把解析结果存入到一个对象中

    • 所存入的对象即为request对象,所以我们可以从request对象中获取请求的相关参数

    • 获取到数据后就可以继续后续的业务,比如获取用户名和密码就可以实现登录操作的相关业务

  • response:==设置==响应数据

    • 业务处理完后,后台就需要给前端返回业务处理的结果即响应数据

    • 把响应数据封装到response对象中

    • 后台服务器[Tomcat]会解析response对象,按照[响应行+响应头+响应体]格式拼接结果

    • 浏览器最终解析结果,把内容展示在浏览器给用户浏览

Request对象

2.1 Request继承体系

跟参数有关

这个时候,我们就需要用到Request继承体系中的**RequestFacade** :

  • 该类实现了HttpServletRequest接口,也间接实现了ServletRequest接口。

  • Servlet类中的service方法、doGet方法或者是doPost方法最终都是由Web服务器[Tomcat]来调用的,所以Tomcat提供了方法参数接口的具体实现类,并完成了对象的创建

  • 要想了解RequestFacade中都提供了哪些方法,我们可以直接查看JavaEE的API文档中关于ServletRequest和HttpServletRequest的接口文档,因为RequestFacade实现了其接口就需要重写接口中的方法

2.2 Request获取请求数据

2.2.1 获取请求行数据
获取请求方式: GET
String getMethod()
获取虚拟目录(项目访问路径): /request-demo
String getContextPath()
获取URL(统一资源定位符): http://localhost:8080/request-demo/req1
StringBuffer getRequestURL()
获取URI(统一资源标识符): /request-demo/req1
String getRequestURI()
获取请求参数(GET方式): username=zhangsan&password=123
String getQueryString()

介绍完上述方法后,咱们通过代码把上述方法都使用下:

复制代码
/**
 * request 获取请求数据
 */
@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // String getMethod():获取请求方式: GET
        String method = req.getMethod();
        System.out.println(method);//GET
        // String getContextPath():获取虚拟目录(项目访问路径):/request-demo
        String contextPath = req.getContextPath();
        System.out.println(contextPath);
        // StringBuffer getRequestURL(): 获取URL(统一资源定位符):http://localhost:8080/request-demo/req1
        StringBuffer url = req.getRequestURL();
        System.out.println(url.toString());
        // String getRequestURI():获取URI(统一资源标识符): /request-demo/req1
        String uri = req.getRequestURI();
        System.out.println(uri);
        // String getQueryString():获取请求参数(GET方式): username=zhangsan
        String queryString = req.getQueryString();
        System.out.println(queryString);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    }
}

启动服务器,访问http://localhost:8080/request-demo/req1?username=zhangsan&passwrod=123,获取的结果如下:

2.2.2 获取请求头数据

String getHeader(String name)

.2.3 获取请求体数据

对于请求体中的数据,Request对象提供了如下两种方式来获取其中的数据,分别是:

  • 获取字节输入流,如果前端发送的是字节数据,比如传递的是文件数据,则使用该方法
复制代码
ServletInputStream getInputStream()
该方法可以获取字节
  • 获取字符输入流,如果前端发送的是纯文本数据,则使用该方法
复制代码
BufferedReader getReader()
2.2.4 获取请求参数的通用方式

对于请求参数的获取,常用的有以下两种:

  • GET方式:
复制代码
String getQueryString()
  • POST方式:
复制代码
BufferedReader getReader();

问题: GET请求和POST请求接收参数的方式不一样

request对象已经将上述获取请求参数的方法进行了封装,并且request提供的方法实现的功能更强大,以后只需要调用request提供的方法即可

(1)根据不同的请求方式获取请求参数,获取的内容如下:

(2)把获取到的内容进行分割,内容如下:

(3)把分割后端数据,存入到一个Map集合中:

注意 :因为参数的值可能是一个,也可能有多个,所以Map的值的类型为String数组。

基于上述理论,request对象为我们提供了如下方法:

  • 获取所有参数Map集合
Map<String,String[]> getParameterMap()
  • 根据名称获取参数值(数组)
String[ ] getParameterValues(String name)
  • 根据名称获取参数值(单个值)
String getParameter(String name)

小结

  • req.getParameter()方法使用的频率会比较高

2.3 IDEA快速创建Servlet

使用通用方式获取请求参数后,屏蔽了GET和POST的请求方式代码的不同,则代码可以定义如下格式:

2.4 请求参数中文乱码问题

2.4.1 POST请求解决方案
  • 分析出现中文乱码的原因:

    • POST的请求参数是通过request的getReader()来获取流中的数据

    • TOMCAT在获取流的时候采用的编码是ISO-8859-1

    • ISO-8859-1编码是不支持中文的,所以会出现乱码

  • 解决方案:

    • 页面设置的编码格式为UTF-8

    • 把TOMCAT在获取流数据之前的编码设置为UTF-8

    • 通过request.setCharacterEncoding("UTF-8")设置编码,UTF-8也可以写成小写

修改后的代码为:

2.4.2 GET请求解决方案

新版本 Tomcat(Tomcat 8 及以上,包括 Tomcat10、Tomcat11)默认已经是 UTF-8 了,GET 请求再也不会中文乱码了

编码和解码学习:

2.5 Request请求转发

==请求转发(forward):一种在服务器内部的资源跳转方式。==

  1. 请求转发的实现方式:
req.getRequestDispatcher("资源B路径").forward(req,resp);

具体如何来使用,我们先来看下需求:

(1)创建RequestDemo5类

复制代码
/**
 * 请求转发
 */
@WebServlet("/req5")
public class RequestDemo5 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("demo5...");
    }
​
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

(2)创建RequestDemo6类

复制代码
/**
 * 请求转发
 */
@WebServlet("/req6")
public class RequestDemo6 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("demo6...");
    }
​
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

(3)在RequestDemo5的doGet方法中进行请求转发

/**

* 请求转发
*/
@WebServlet("/req5")
public class RequestDemo5 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo5...");
//请求转发
request.getRequestDispatcher("/req6").forward(request,response);
}

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

request对象提供的三个方法:

  • 存储数据到request域[范围,数据是存储在request对象]中
复制代码
void setAttribute(String name,Object o);
  • 根据key获取值
复制代码
Object getAttribute(String name);
  • 根据key删除该键值对
复制代码
void removeAttribute(String name);

(1)修改RequestDemo5中的方法

@WebServlet("/req5")

public class RequestDemo5 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo5...");
//存储数据
request.setAttribute("msg","hello");
//请求转发
request.getRequestDispatcher("/req6").forward(request,response);
}

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

(2)修改RequestDemo6中的方法

/**

* 请求转发
*/
@WebServlet("/req6")
public class RequestDemo6 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("demo6...");
//获取数据
Object msg = request.getAttribute("msg");
System.out.println(msg);

}

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

3,Response对象

Reponse的继承体系

3.1 Response设置响应数据功能介绍

HTTP响应数据总共分为三部分内容,分别是==响应行、响应头、响应体==,对于这三部分内容的数据,respone对象都提供了哪些方法来进行设置?

响应行

复制代码
void setStatus(int sc);

响应头

复制代码
void setHeader(String name,String value);

响应体

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

获取字符输出流:

复制代码
PrintWriter getWriter();

获取字节输出流

复制代码
ServletOutputStream getOutputStream();
  1. 重定向的特点
  • 浏览器地址栏路径发送变化

    当进行重定向访问的时候,由于是由浏览器发送的两次请求,所以地址会发生变化

  • 可以重定向到任何位置的资源(服务内容、外部均可)

    因为第一次响应结果中包含了浏览器下次要跳转的路径,所以这个路径是可以任意位置资源。

  • 两次请求,不能在多个资源使用request共享数据

    因为浏览器发送了两次请求,是两个不同的request对象,就无法通过request对象进行共享数据

介绍完==请求重定向==和==请求转发==以后,接下来需要把这两个放在一块对比下:

3.3 路径问题

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

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

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

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

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

掌握了这个规则,接下来就通过一些练习来强化下知识的学习:

  • <a href='路劲'>

  • <form action='路径'>

  • req.getRequestDispatcher("路径")

  • resp.sendRedirect("路径")

答案:

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

3.4 Response响应字符数据

字符数据 两个步骤:

  • 通过Response对象获取字符输出流: PrintWriter writer = resp.getWriter();

  • 通过字符输出流写数据: writer.write("aaa");

  1. 返回一串html字符串 ,并且能被浏览器解析
PrintWriter writer = response.getWriter();

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

2 .返回一个中文的字符串你好需要注意设置响应数据的编码为utf-8

//设置响应的数据格式及数据的编码

response.setContentType("text/html;charset=utf-8");
writer.write("你好");

字节数据 两个步骤:

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

  • 通过字节输出流写数据: outputStream.write(字节数据);

(1)pom.xml添加依赖

复制代码
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.6</version>
</dependency>

(2)调用工具类方法

复制代码
//fis:输入流
//os:输出流
IOUtils.copy(fis,os);

优化后的代码:

相关推荐
BduL OWED2 小时前
Docker:基于自制openjdk8镜像 or 官方openjdk8镜像,制作tomcat镜像
docker·容器·tomcat
misL NITL14 小时前
idea、mybatis报错Property ‘sqlSessionFactory‘ or ‘sqlSessionTemplate‘ are required
tomcat·intellij-idea·mybatis
idolao19 小时前
CentOS 7 安装 jakarta-tomcat-connectors-jk2-src-current.tar.gz 详细步骤(解压、编译、配置)
linux·centos·tomcat
薪火铺子21 小时前
SpringBoot WebServer启动与监听器原理深度解析
spring boot·后端·tomcat
子木HAPPY阳VIP2 天前
信创UOS,Docker 完整操作部署(Dockerfile部署方式)&排错整合
linux·运维·redis·nginx·docker·容器·tomcat
橙子圆1232 天前
Mybatis之动态sql
sql·tomcat·mybatis
天码-行空2 天前
深入拆解 Tomcat 架构:高层组件与启动流程设计
java·架构·tomcat
天码-行空2 天前
深入拆解 Tomcat 架构:一键启停与生命周期设计
java·架构·tomcat
子木HAPPY阳VIP2 天前
Tomcat 9 + JSP 中文乱码终极解决方案(完整版可复制)
java·开发语言·docker·tomcat·jsp