第五章 Servlet

九 请求转发和响应重定向

9.1 概述
什么是请求转发和响应重定向
  • 请求转发 和 响应重定向 是 web应用中间接访问项目资源 的两种手段,也是Servlet控制页面跳转的两种手段

  • 请求转发通过HttpServletRequest实现,响应重定向通过HttpServletResponse实现

  • 请求转发生活举例: 张三找李四借钱,李四没有,李四找王五,让王五借给张三

  • 响应重定向生活举例:张三找李四借钱,李四没有,李四让张三去找王五,张三自己再去找王五借钱

9.2 请求转发
  • A- 请求转发运行逻辑图

  • B- 请求转发特点
  • 请求转发通过HttpServletRequest对象获取请求转发器实现

  • 请求转发是服务器内部的行为,对客户端是屏蔽的

  • 客户端只发送了一次请求,客户端地址栏不变

  • 服务端只产生了一对请求和响应对象,这一对请求和响应对象会继续传递给下一个资源

  • 因为全程只有一个HttpServletRequset对象,所以请求参数可以传递,请求域中的数据也可以传递

  • 请求转发可以转发给其他Servlet动态资源,也可以转发给一些静态资源以实现页面跳转

  • 请求转发可以转发给WEB-INF下受保护的资源

  • 请求转发不能转发到本项目以外的外部资源

  • C- 请求转发测试代码

测试的核心逻辑:

servletA -> 请求转发至 -> servletB

  • servlet A
//TODO-3 请求转发测试

//  获取请求转发器
//  转发给servlet ok
RequestDispatcher requestDispatcher = req.getRequestDispatcher("servletB");
//  转发给给一个视图资源 ok
RequestDispatcher requestDispatcher1 = req.getRequestDispatcher("welcome.html");
//  转发给WEB-INF下的资源 ok
RequestDispatcher requestDispatcher2 = req.getRequestDispatcher("/WEB-INF/views/view1.html");
//  转发给外部资源 no
RequestDispatcher requestDispatcher3 = req.getRequestDispatcher("http://www.baidu.com");

//  获取请求参数
String username = req.getParameter("username");
System.out.println("servletA获取的参数为: "+username);

//  向请求域中添加数据
req.setAttribute("reqKey","requestMessage");
System.out.println("现在还在servletA...");

//  做出转发动作
requestDispatcher.forward(req,resp);
  • servlet B
//TODO-3 请求转发测试 (接收)

//  获取请求参数
String username = req.getParameter("username");
System.out.println( "请求转发至servletB中的参数username: "+username);

//  获取请求域中的数据
String reqMessage = (String) req.getAttribute("reqKey");
System.out.println("servletA中新添加的参数在servletB中获取,为: "+reqMessage);

//  做出响应
resp.setCharacterEncoding("GBK");
resp.getWriter().write("servletA 请求转发至servletB ,请求转发测试成功");
  • url访问

http:// localhost : 8080 //web_all_02_war_exploded/serverA?username=zhangsan

  • 网页显示信息
servletA 请求转发至servletB ,请求转发测试成功
  • 控制台显示信息

9.3 响应重定向
  • A- 响应重定向运行逻辑图

  • B- 响应重定向特点
  • 响应重定向通过HttpServletResponse对象的sendRedirect方法实现

  • 响应重定向是服务端通过302响应码和路径,告诉客户端自己去找其他资源,是在服务端提示下的,客户端的行为

  • 客户端至少发送了两次请求,客户端地址栏是要变化的

  • 服务端产生了多对请求和响应对象,且请求和响应对象不会传递给下一个资源

  • 因为全程产生了多个HttpServletRequset对象,所以请求参数不可以传递,请求域中的数据也不可以传递

  • 重定向可以是其他Servlet动态资源,也可以是一些静态资源以实现页面跳转

  • 重定向不可以到给WEB-INF下受保护的资源

  • 重定向可以到本项目以外的外部资源

  • C- 响应重定向测试代码

测试的核心逻辑:

  1. servletA -> 重定向到 servlet动态资源 -> servletB
  2. servletA -> 重定向到视图静态资源 -> "welcome.html"
  3. servletA -> 重定向到WEB-INF下的资源 -> "WEB-INF/views/view1.html"
  4. servletA -> 重定向到外部资源 -> "https : // www. baidu.com"
  • servletA
        //TODO-4 响应重定向测试

        //  获取请求参数
        String username = req.getParameter("username");
        System.out.println("servletA获取的参数为: "+username);
        //  向请求域中添加数据
        req.setAttribute("reqKey","requestMessage");
        //  响应重定向
        //  重定向到 servlet动态资源  ok
//        resp.sendRedirect("servletB");
        //  重定向到视图静态资源  ok
//        resp.sendRedirect("welcome.html");
        //  重定向到WEB-INF下的资源  no
//        resp.sendRedirect("WEB-INF/views/view1.html");
        //  重定向到外部资源
        resp.sendRedirect("https://www.baidu.com");
  • servletB
//TODO-4 响应重定向测试 (接收)

//  获取请求参数
String username = req.getParameter("username");
System.out.println("响应重定向至servletB中的参数username: "+username);
//  获取请求域中的数据
String reqMessage = (String) req.getAttribute("reqKey");
System.out.println("servletA中新添加的参数在servletB中获取,为: "+reqMessage);
//  做出响应
resp.setCharacterEncoding("GBK");
resp.getWriter().write("servletA 响应重定向至servletB ,响应重定向测试成功");
  • welcome.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>HttpServletResponse 响应重定向</title>
</head>
<body>
    响应重定向特点
<br>
    - 响应重定向通过HttpServletResponse对象的sendRedirect方法实现
<br>
    - 响应重定向是服务端通过302响应码和路径,告诉客户端自己去找其他资源,是在服务端提示下的,客户端的行为
<br>
    - 客户端至少发送了两次请求,客户端地址栏是要变化的
<br>
    - 服务端产生了多对请求和响应对象,且请求和响应对象不会传递给下一个资源
<br>
    - 因为全程产生了多个HttpServletRequset对象,所以请求参数不可以传递,请求域中的数据也不可以传递
<br>
    - 重定向可以是其他Servlet动态资源,也可以是一些静态资源以实现页面跳转
<br>
    - 重定向不可以到给WEB-INF下受保护的资源
<br>
    - 重定向可以到本项目以外的外部资源
<br>
</body>
</html>
  • view1.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  响应重定向
</body>
</html>

  • url访问

http:// localhost : 8080 //web_all_02_war_exploded/serverA?username=zhangsan

  • 网页显示信息
  1. servletA 响应重定向至servletB ,响应重定向测试成功
  • 控制台显示信息


    十 web乱码和路径问题总结

    10.1 乱码问题
    10.1.0 乱码问题产生的根本原因是什么
    • 数据的编码和解码使用的不是同一个字符集

    • 使用了不支持某个语言文字的字符集

    各个字符集的兼容性

    10.1.1 HTML乱码问题
    • A- 设置项目文件的字符集要使用一个支持中文的字符集
    • 查看当前文件的字符集

    • 查看项目字符集 配置,将Global Encoding 全局字符集,Project Encoding 项目字符集, Properties Files 属性配置文件字符集设置为UTF-8

    • B- 当前视图文件的字符集通过<meta charset="UTF-8"> 来告知浏览器通过什么字符集来解析当前文件

    10.1.2 Tomcat控制台乱码
    • A- 在tomcat10.1.7这个版本中,修改 tomcat/conf/logging.properties中,所有的UTF-8为GBK即可
    • 修改前

    • 修改后

    • B- sout乱码问题,设置JVM加载.class文件时使用UTF-8字符集
    • 设置虚拟机加载.class文件的字符集和编译时使用的字符集一致

    10.1.3 请求乱码问题
    • 10.1.3.1 GET请求乱码

    A- GET请求方式乱码分析

    • GET方式提交参数的方式是将参数放到URL后面,如果使用的不是UTF-8,那么会对参数进行URL编码处理

    • HTML中的 <meta charset='字符集'/> 影响了GET方式提交参数的URL编码

    • tomcat10.1.7 的URI编码默认为 UTF-8

    • 当GET方式提交的参数URL编码和tomcat10.1.7默认的URI编码不一致时,就会出现乱码

    B- GET请求方式乱码演示

    • 浏览器解析的文档的<meta charset="GBK" />

    • GET方式提交时,会对数据进行URL编码处理 ,是将GBK 转码为 "百分号码"

    • tomcat10.1.7 默认使用UTF-8对URI进行解析,造成前后端使用的字符集不一致,出现乱码

    C- GET请求方式乱码解决

    • 方式1 :设置GET方式提交的编码和Tomcat10.1.7的URI默认解析编码一致即可 (推荐)


    • 方式2 : 设置Tomcat10.1.7的URI解析字符集和GET请求发送时所使用URL转码时的字符集一致即可,修改conf/server.xml中 Connecter 添加 URIEncoding="GBK" (不推荐)


    • 10.1.3.2 POST方式请求乱码

    A- POST请求方式乱码分析

    • POST请求将参数放在请求体中进行发送

    • 请求体使用的字符集受到了<meta charset="字符集"/> 的影响

    • Tomcat10.1.7 默认使用UTF-8字符集对请求体进行解析

    • 如果请求体的URL转码和Tomcat的请求体解析编码不一致,就容易出现乱码

    B- POST方式乱码演示

    • POST请求请求体受到了<meta charset="字符集"/> 的影响

    • 请求体中,将GBK数据进行 URL编码

    • 后端默认使用UTF-8解析请求体,出现字符集不一致,导致乱码

    C- POST请求方式乱码解决

    • 方式1 : 请求时,使用UTF-8字符集提交请求体 (推荐)

    • 方式2 : 后端在获取参数前,设置解析请求体使用的字符集和请求发送时使用的字符集一致 (不推荐)

    10.1.4 响应乱码问题

    A- 响应乱码分析

    • 在Tomcat10.1.7中,向响应体中放入的数据默认使用了工程编码 UTF-8

    • 浏览器在接收响应信息时,使用了不同的字符集或者是不支持中文的字符集就会出现乱码

    B- 响应乱码演示

    • 服务端通过response对象向响应体添加数据

    • 浏览器接收数据解析乱码

    C- 响应乱码解决

    • 方式1 : 手动设定浏览器对本次响应体解析时使用的字符集(不推荐)

    edge和 chrome浏览器没有提供直接的比较方便的入口,不方便

    • 方式2: 后端通过设置响应体的字符集和浏览器解析响应体的默认字符集一致(不推荐)

    • 方式3: 通过设置content-type响应头,告诉浏览器以指定的字符集解析响应体(推荐)


    10.2 路径问题
    10.2.1 前端路径问题
    10.2.2 重定向中的路径问题
    10.2.3 请求转发中的路径问题

    十一 MVC架构模式

    • MVC架构是什么

    MVC(Model View Controller)是软件工程中的一种软件架构模式,它把软件系统分为模型视图控制器三个基本部分。用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。


    • MModel 模型层,具体功能如下

      1. 存放和数据库对象的实体类以及一些用于存储非数据库表完整相关的VO对象

      2. 存放一些对数据进行逻辑运算操作的的一些业务处理代码

    • VView 视图层,具体功能如下

      1. 存放一些视图文件相关的代码 html css js等

      2. 在前后端分离的项目中,后端已经没有视图文件,该层次已经衍化成独立的前端项目

    • CController 控制层,具体功能如下

      1. 接收客户端请求,获得请求数据

      2. 将准备好的数据响应给客户端


    MVC模式下,项目中的常见包

    • M:

      1. 实体类包(pojo /entity /bean) 专门存放和数据库对应的实体类和一些VO对象

      2. 数据库访问包(dao/mapper) 专门存放对数据库不同表格CURD方法封装的一些类

      3. 服务包(service) 专门存放对数据进行业务逻辑运算的一些

    • V:

      1. web目录下的视图资源 html css js img 等

      2. 前端工程化后,在后端项目中已经不存在了

    • C:
    1. 控制层包(controller)
    • MVC架构图解

    A- 非前后端分离的MVC

    B- 前后端分离的MVC

    Logo

    汇聚全球AI编程工具,助力开发者即刻编程。

    更多推荐