基于本文回答

播面 播面

文图音视,全方位拆解八股文
0
评论

如何在 Controller 之间进行重定向(Redirect)和转发(Forward)?

知识点图片

在 Java Web 开发中(主要是 Spring MVC / Spring Boot 环境),Controller 之间的跳转主要有两种方式:重定向(Redirect)转发(Forward)

以下是具体的实现代码和两者之间的区别。


1. 重定向 (Redirect)

特点:

  • 客户端行为:服务器告诉浏览器“去访问另一个地址”。
  • URL 会变:浏览器地址栏会变成新的 URL。
  • 请求不共享:这是一个全新的 Request,上一个请求的数据(request 作用域)会丢失,除非使用 Session 或 URL 参数传递。

实现方式 A:返回 String (最常用)

使用 redirect: 前缀。

java
@Controller
@RequestMapping("/order")
public class OrderController {

    @GetMapping("/save")
    public String saveOrder() {
        // 处理业务逻辑...
        System.out.println("订单保存成功");
        
        // 重定向到 /order/list
        return "redirect:/order/list"; 
    }

    @GetMapping("/list")
    public String listOrders() {
        return "order_list_page"; // 返回视图名称
    }
}

实现方式 B:使用 ModelAndView

java
@GetMapping("/save")
public ModelAndView saveOrder() {
    ModelAndView mv = new ModelAndView();
    mv.setViewName("redirect:/order/list");
    return mv;
}

如何在重定向中传递数据?

由于 Request 域不共享,通常使用 RedirectAttributes (Flash Attributes) 来传递临时数据。

java
@PostMapping("/login")
public String login(String username, RedirectAttributes attributes) {
    // 模拟登录失败
    attributes.addFlashAttribute("msg", "用户名或密码错误");
    // 重定向回登录页,msg 数据在重定向后依然可用(一次性)
    return "redirect:/loginPage";
}

2. 转发 (Forward)

特点:

  • 服务器端行为:服务器内部将请求交给另一个 Controller 处理。
  • URL 不变:浏览器地址栏显示的还是原来的 URL。
  • 请求共享:使用的是同一个 Request 对象,数据(request.setAttribute)可以共享。

实现方式 A:返回 String (最常用)

使用 forward: 前缀。

java
@Controller
@RequestMapping("/api")
public class ApiController {

    @GetMapping("/check")
    public String checkUser(HttpServletRequest request) {
        System.out.println("正在检查用户权限...");
        
        // 可以在 request 中放入数据传给下一个 Controller
        request.setAttribute("username", "admin");
        
        // 转发到 /api/process
        return "forward:/api/process";
    }

    @GetMapping("/process")
    public String processUser(HttpServletRequest request) {
        // 可以获取上一个 Controller 设置的数据
        String user = (String) request.getAttribute("username");
        System.out.println("处理用户: " + user);
        return "result_page";
    }
}

实现方式 B:使用 ModelAndView

java
@GetMapping("/check")
public ModelAndView checkUser() {
    ModelAndView mv = new ModelAndView();
    mv.setViewName("forward:/api/process");
    return mv;
}

3. 总结与对比

特性 重定向 (Redirect) 转发 (Forward)
发生位置 客户端(浏览器) 服务器内部
请求次数 2 次请求 1 次请求
URL 地址栏 会发生变化 不会变化
数据共享 无法直接共享 Request 数据 (需用 FlashAttribute 或 Session) 共享同一个 Request 数据
应用场景 防止表单重复提交(Post/Redirect/Get 模式)、跳转到外部网站 内部逻辑流转、权限校验后转交业务处理
代码前缀 return "redirect:/..." return "forward:/..."

什么时候用哪个?

  1. 使用重定向 (Redirect):当你完成了一个动作(如提交表单、删除数据、登录成功),不希望用户刷新页面导致重复提交时。
  2. 使用转发 (Forward):当你需要将请求拆分处理,或者仅仅是想复用另一个 Controller 的逻辑,且希望对用户隐藏内部跳转细节时。
00:00
00:00