Servlet-学习笔记-下
9. 请求转发和响应重定向
9.1 概述
什么是请求转发和响应重定向
-
请求转发和响应重定向是web应用中间接访问项目资源的两种手段,也是Servlet控制页面跳转的两种手段
-
请求转发通过HttpServletRequest 实现,响应重定向通过HttpServletResponse 实现
-
请求转发生活举例:张三找李四借钱,李四没有,李四找王五,让王五借给张三
-
响应重定向生活举例:张三找李四借钱,李四没有,李四让张三找王五,张三自己再去找王五借钱
9.2 请求转发
请求转发运行逻辑图
-
请求转发时,请求和响应对象会继续传递给下一个资源
-
请求中的参数可以继续向下传递
-
请求转发时服务器内部的行为,客户端是不知道的
-
客户端只产生了一次请求
请求转发的特点
-
1 请求转发是通过HttpServletRequest 对象实现的
-
2 请求转发是服务器内部行为,对客户端是屏蔽的
-
3 客户端只产生了一次请求 服务端只产生了一对 request 和 response 对象
-
4 客户端的地址栏是不变的
-
5 请求的参数是可以继续传递的
-
6 目标资源可以是servlet动态资源 也可以是html静态资源
-
7 目标资源可以是WEB-INF 下的受保护资源 该方式也是WEB-INF 下的资源的唯一访问方式
-
8 目标资源不可以是项目外部的资源
代码实现
package com.mdklea.servlet;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 1 请求转发是通过HttpServletRequest 对象实现的
* 2 请求转发是服务器内部行为,对客户端是屏蔽的
* 3 客户端只产生了一次请求 服务端只产生了一对 request 和 response 对象
* 4 客户端的地址栏是不变的
* 5 请求的参数是可以继续传递的
* 6 目标资源可以是servlet动态资源 也可以是html静态资源
* 7 目标资源可以是WEB-INF 下的受保护资源 该方式也是WEB-INF 下的资源的唯一访问方式
* 8 目标资源不可以是项目外部的资源
*/
@WebServlet("/servletA")
public class ServletA extends HttpServlet{
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("ServletA启动了");
// 获取请求转发器
//RequestDispatcher requestDispatcher = req.getRequestDispatcher("servletB");
// 让请求转发器做出转发动作
//requestDispatcher.forward(req,resp);
RequestDispatcher requestDispatcher = req.getRequestDispatcher("a.html");
requestDispatcher.forward(req,resp);
}
}
9.3 响应重定向
相应重定向逻辑图
相应重定向的特点
-
1 相应重定向通过HttpServletResponse 对象的sendRedirect 方法实现
-
2 相应重定向是服务端通过302响应码和路径,告诉客户端自己去找其他资源,实在服务端提示下的,客户端的行为
-
3 客户端至少发送了两次请求,客户端地址栏是要变化的
-
4 服务端产生了多对请求和响应对象,且请求和响应对象不会传递给下一个资源
-
5 因为全程产生了多个HttpServletRequest对象,所以请求参数不可以传递,请求域中的数据也不可以传递
-
6 重定向可以是其他Servlet动态资源,也可以是一些静态资源以实现页面跳转
-
7 重定向不可以给到WEB-INF 下受保护的资源
-
8 重定向可以到本项目以外的外部资源
9.4 重点
同样能够实现跳转,优先使用响应重定向
10 web乱码问题和路径问题总结
10.1 乱码问题
乱码问题产生的根本原因是什么
-
数据的编码和解码使用的不是同一个字符集
-
使用了不支持某个语言文字的字符集
各个字符集的兼容性
-
由上图得知,上浮字符集都兼容了ASCII
-
ASCII中有什么?英文字母和一些通常使用的符号,所以这些东西无论使用什么字符集都不会乱码
10.1.1 HTML乱码问题
查看当前文件的字符集
查看项目字符集,配置,将Global Encoding 全局字符集,Project Encoding 项目字符集,Properties Files 属性配置文件字符集设置为UTF-8
TomCat控制台乱码
在tomcat中,修改tomcat/conf/logging.properties中,所有的UTF-8更改为GBK即可
sout 乱码问题,设置JVM加载.class文件时使用UTF-8字符集
-
设置虚拟机加载.class文件的字符集和编译时使用的字符集一致
10.1.2 请求乱码问题
10.1.2.1GET请求乱码
GET请求方式乱码分析
-
GET方式提交参数的方式是将参数放到URL后面,如果使用的不是UTF-8,那么会对参数进行URL编码处理
-
HTML中的<meta charset='字符集/'> 影响了GET方式提交参数的URL编码
-
tomcat10.1.7 的URL编码默认为 UTF-8
-
当GET方式提交的参数URL编码和tomcat10.1.7默认的URL编码不一致时就会出现乱码
10.1.2.2 POST方式请求乱码
POST请求方式乱码分析
-
POST请求将参数放在请求体中进行发送
-
请求体使用的字符集受到了<meta charset="字符集"/>的影响
-
Tomcat10.1.7默认使用UTF-8字符集对请求体进行解析
-
如果请求体的URL转码和Tomcat的请求体解析编码不一致,就容易出现乱码
package com.mdklea.servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/servletC")
public class ServletC extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 设置响应体使用UTF-8编码
resp.setCharacterEncoding("GBK");
// 设置Context-Type 响应头,告诉客户端用UTF-8编码
resp.setContentType("text/html;charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.write("<h1>你好,你好,你好,你好,你好,我的头发,是真发!</h1>");
/**
* Tomcat10中,响应体默认的编码字符集使用的是UTF-8
* 响应头
* 相应行
* 响应体 你好 Hello (UTF-8)
*
* 解决思路
* 1 可以设置响应体的编码字符集和客户端的保持一致 不推荐 客户端解析的字符集是无法预测的
* 2 可以告诉客户端使用指定的字符集进行解码 通过设置Content-Type 响应头
*/
}
}
10.2 路径问题
10.2.1相对路径和绝对路径
相对路径
-
相对路径的规则是:以当前资源所在的路径为出发点去寻找目标资源
-
相对路径不以/开头
-
在file协议下,使用的是磁盘路径
-
在http协议下,使用的是url路径
-
相对路径中可以使用./表示当前资源所在路径,可以省略不写
-
相对路径中可以使用../表示当前资源所在路径的上一层路径,需要时手动添加
绝对路径
-
绝对路径的规则是:使用一个固定的路径做出出发点去寻找目标资源,和当前资源所在的路径没有关系
-
绝对路径要以/开头
-
绝对路径的写法中,不以当前资源的所在路径为出发点,所以不会出现./和../
-
不同项目和不同的写一下,绝对路径的基础位置可能不同,寻找目标资源路径的写法都一致
应用场景
-
前端代码中,href src action 等属性
-
请求转发和重定向中的路径
10.2.1.1 前端路径问题
相对路径
以当前资源的所在路径为出发点去找目标资源
语法:不以/为开头
./表示当前资源的上一层路径
缺点:目标资源路径受到当前资源路径的影响 不同的位置,相对路径写法不同
绝对路径
始终以固定的路径作为出发点去找目标资源 和当前资源所在路径没有关系
语法:以/开头
不同的项目中,固定的路径出发点可能不一致,可以测试一下
优点:目标资源路径的写法不会受到当前资源路径的影响,不同的位置,绝对路径写法一致
缺点:绝对路径要补充项目的上下文,项目上下文是可以改变的
通过head>base>herf 属性,定义相对路径公共前缀,通过公共前缀把一个相对路径转换为绝对路径(不完美)
10.2.1.2 重定向路径问题
重定向到ServletB
-
相对路径写法
和前端的相对路径规则一致
resp.sendRedirect("servletB")
-
绝对路径写法
http://localhost:8080/开头
resp.sendRedirect("/d05/servletB")
10,2,1,3 请求转发到ServletB
-
相对路径写法 一致
http://localhost:8080/d05/servletA
-
绝对路径
请求转发的绝对路径是不需要添加项目上下文的
请求转发的/ 代表的路径是 http://localhost:8080/d05/
最终解决方式:设置项目路径为/