Servlet 转发与重定向

一、先搞懂核心概念:什么是转发?什么是重定向?

  1. 请求转发(Request Forward)
    大白话:服务器内部帮你 “跑腿”,你只需要给服务器发一次请求,服务器自己在内部跳转到另一个资源,最后把结果给你,你全程不用动。
    image

核心特点(必背):

  • 1 次请求,1 次响应
  • 浏览器地址栏不会变(还是 Servlet1 的地址)
  • 可以共享 request 里的数据(比如 setAttribute 存的参数)
  • 是服务器内部跳转,客户端完全感知不到
  1. 响应重定向(Response Redirect)
    大白话:服务器告诉你 “我这处理不了,你去另一个地址找它”,然后浏览器自己再发一次新请求,跳转到目标地址。

image

核心特点(必背):
2 次请求,2 次响应

  • 浏览器地址栏会变(变成新的目标地址)
  • 不能共享 request 里的数据(因为是两次完全独立的请求)
  • 是客户端跳转,浏览器会主动发起新请求
    二、转发 vs 重定向 核心区别对照表
    image

三、完整流程拆解

  1. 请求转发流程
    客户端 → 发送请求到 ServletA → ServletA 转发请求到 ServletB(服务器内部) → ServletB 处理后响应给客户端
    (1次请求,1次响应,地址栏始终是 ServletA 的地址)
    image
    image
    image

对应案例(第一张图代码):

  • Servlet1 用 setAttribute 把 name=zhangsan 存到 request 里
  • 用 forward 转发到 Servlet2
  • Servlet2 用 getAttribute 拿到 name,输出 Hellozhangsan
  • 浏览器地址栏还是 /servlet1,但显示的是 Servlet2 的内容
  1. 重定向流程

客户端 → 发送请求到 ServletA → ServletA 返回302响应,告诉浏览器去访问新地址 → 浏览器主动发新请求到 ServletB → ServletB 响应给客户端
(2次请求,2次响应,地址栏变成 ServletB 的新地址)

image
image

对应案例:

  1. 用户在登录页输入账号密码,提交到 LoginServlet
  2. 账号密码正确,LoginServlet 调用 sendRedirect("index.jsp")
  3. 浏览器收到 302 响应,自动跳转到 index.jsp,地址栏变成 index.jsp 的地址
  4. 账号密码错误,跳转到 info.html 提示错误

四、配套核心知识点(必须掌握)

  1. Request 相关方法(获取请求信息)
    image

  2. Request 数据共享方法
    image
    ⚠️ 注意:只有转发能共享 request 数据,重定向不行,因为重定向是两次独立请求,request 对象不是同一个。

  3. Response 输出流方法
    image

  4. Java 中 == 和 equals () 的区别(登录代码用到)
    image
    登录代码正确写法:
    image

五、新手避坑指南(90% 的人会踩的坑)

  1. 转发和重定向的路径问题
    转发:路径以 / 开头,代表项目根目录(比如 /servlet2)
    重定向:路径可以写相对路径(比如 index.jsp),也可以写绝对路径(比如 /项目名/index.jsp),如果是外部网址直接写完整地址(比如 https://www.baidu.com
  2. 转发后不要写多余代码
    转发后,后续代码依然会执行,不要在 forward 后写多余的输出逻辑,避免报错。
  3. 重定向后数据丢失
    重定向是两次请求,request 里存的数据会完全丢失,如果需要传参,只能用 ? 拼在 URL 后面(比如 index.jsp?name=zhangsan),或者用 session 存数据。
  4. 表单重复提交问题
    表单提交后,用重定向而不是转发,避免用户刷新页面重复提交表单。
  5. 字符串比较的坑
    永远用 equals() 比较字符串内容,不要用 ==,尤其是用户输入的参数。
    六、傻瓜式使用场景总结(直接套用)
    image
    七、完整代码示例(直接复制运行)
  6. 请求转发完整代码
    Servlet1.java

package com.example.unit2_5;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/servlet1")
public class Servlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 给request域存数据,转发时共享
req.setAttribute("name", "zhangsan");
// 2. 转发到Servlet2,req和resp对象传递过去
req.getRequestDispatcher("/servlet2").forward(req, resp);
}
}

Servlet2.java

package com.example.unit2_5;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/servlet2")
public class Servlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 从request域取Servlet1存的数据
String name = req.getAttribute("name").toString();
// 2. 输出响应给浏览器
PrintWriter out = resp.getWriter();
out.println("

Hello" + name + "

");
}
}

运行效果:访问 localhost:8080/项目名/servlet1,地址栏不变,显示 Hellozhangsan
2. 重定向登录完整代码
login.html(登录页面)

登录
用户名:
密码:

LoginServlet.java

package com.example.unit2_5;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 获取前端传的用户名和密码
String username = req.getParameter("username");
String password = req.getParameter("password");
PrintWriter out = resp.getWriter();

// 2. 校验账号密码(正确账号root,密码root)
if ("root".equals(username) && "root".equals(password)) {
System.out.println("登录成功!");
// 3. 登录成功,重定向到index.jsp
resp.sendRedirect("index.jsp");
} else {
System.out.println("登录失败!");
// 4. 登录失败,重定向到info.html提示错误
resp.sendRedirect("info.html");
}
}
}

运行效果:
输入 root/root,跳转到 index.jsp,地址栏变为 index.jsp
输入错误账号密码,跳转到 info.html,地址栏变为 info.html
八、终极记忆口诀(背会就不会忘)
转发:一次请求地址不变,服务器内部数据共享
重定向:两次请求地址改变,客户端跳转数据不共享
字符串比较:== 比地址,equals 比内容,字符串比较用 equals

posted @ 2026-04-12 08:28  abchhhh  阅读(31)  评论(0)    收藏  举报