杰瑞科技汇

Java如何实现页面跳转?

Web 后端应用 (Java Web)

这是最常见的情况,用户在浏览器中点击一个链接或提交一个表单,服务器端的 Java 代码处理请求,然后告诉浏览器应该跳转到哪个新页面,这里的“跳转”分为两种:客户端跳转(重定向)服务器端跳转(转发)

Java如何实现页面跳转?-图1
(图片来源网络,侵删)

客户端跳转 (Redirect - 重定向)

原理:服务器返回一个特殊的 HTTP 响应,状态码为 302307,并在响应头中包含一个 Location 字段,值为目标页面的 URL,浏览器接收到这个响应后,会自动向 Location 指定的 URL 发送一个新的请求,这个过程对用户来说是可见的,浏览器地址栏的 URL 会发生变化。

特点

  • 浏览器地址栏 URL 会改变。
  • 两次请求,服务器无法共享 request 范围内的数据(除非使用 session)。
  • 可以跳转到外部网站(https://www.google.com)。

实现方式

使用 Servlet API (原生 Java Web)

Java如何实现页面跳转?-图2
(图片来源网络,侵删)
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("/redirectExample")
public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置重定向的目标URL
        String targetUrl = "/newPage.jsp"; // 相对路径
        // 或者 String targetUrl = "https://www.example.com"; // 绝对路径,可跳转外部
        // 执行重定向
        response.sendRedirect(targetUrl);
    }
}

使用 Spring Boot (现代主流框架)

在 Spring MVC 的控制器方法中,非常简单。

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.view.RedirectView;
@Controller
public class RedirectController {
    // 方法一:直接返回字符串框架会自动重定向
    @GetMapping("/old-path")
    public String redirectToNewPage() {
        return "redirect:/new-page"; // "redirect:" 是 Spring 的特殊前缀
    }
    // 方法二:使用 RedirectView 对象(更灵活)
    @GetMapping("/old-path-view")
    public RedirectView redirectToNewPageView() {
        RedirectView redirectView = new RedirectView();
        redirectView.setUrl("/another-page");
        return redirectView;
    }
}

服务器端跳转 (Forward - 转发)

原理:跳转操作完全在服务器内部完成,服务器将当前请求的处理权直接交给另一个资源(如 Servlet 或 JSP),浏览器对此毫不知情,地址栏的 URL 不会改变。

特点

Java如何实现页面跳转?-图3
(图片来源网络,侵删)
  • 浏览器地址栏 URL 不会改变。
  • 只有一次请求,可以在多个资源之间共享 requestresponse 对象,非常适合在跳转前设置一些数据。
  • 只能跳转到当前 Web 应用内部的资源,不能跳转到外部网站。

实现方式

使用 Servlet API (原生 Java Web)

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("/forwardExample")
public class ForwardServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 在转发前可以设置一些数据,在目标页面中可以获取
        request.setAttribute("message", "这是从 ForwardServlet 传递过来的数据");
        // 获取请求转发器
        RequestDispatcher dispatcher = request.getRequestDispatcher("/targetPage.jsp");
        // 执行转发
        dispatcher.forward(request, response);
    }
}

在 JSP 中实现转发

<%
    // 可以在 JSP 脚本片段中实现转发
    request.setAttribute("jspMessage", "这是从 JSP 页面传递的数据");
    RequestDispatcher dispatcher = request.getRequestDispatcher("/another.jsp");
    dispatcher.forward(request, response);
%>

使用 Spring Boot

在 Spring MVC 中,转发不是直接暴露的 API,因为框架鼓励使用重定向或返回视图名,但如果你想实现类似效果,可以返回视图名,Spring 会默认使用 RequestDispatcher 进行转发。

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class ForwardController {
    @GetMapping("/forward-target")
    public String showTargetPage() {
        // 直接返回视图名,框架会默认进行服务器端转发
        // 假设你配置了视图解析器,它会找到 /WEB-INF/views/target-page.jsp
        return "target-page"; 
    }
}

桌面应用 (Java Swing / JavaFX)

在桌面应用中,“跳转”通常指的是在同一个窗口内切换显示不同的界面(面板 JPanel 或场景 Scene),或者打开一个新的窗口(JFrameStage)。

在同一个窗口内切换视图 (卡片式布局)

这是最常用的方式,比如一个软件的登录界面、主界面、设置界面都在同一个窗口中切换。

使用 Java Swing (CardLayout)

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
public class CardLayoutExample {
    public static void main(String[] args) {
        JFrame frame = new JFrame("卡片布局示例");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(400, 300);
        // 1. 创建一个主面板,使用 CardLayout
        JPanel mainPanel = new JPanel(new CardLayout());
        // 2. 创建不同的“卡片”(界面)
        JPanel loginPanel = createLoginPanel(mainPanel);
        JPanel homePanel = createHomePanel(mainPanel);
        // 3. 将卡片添加到主面板,并给每个卡片一个名字
        mainPanel.add(loginPanel, "LOGIN");
        mainPanel.add(homePanel, "HOME");
        // 4. 默认显示登录界面
        ((CardLayout) mainPanel.getLayout()).show(mainPanel, "LOGIN");
        frame.add(mainPanel);
        frame.setVisible(true);
    }
    // 创建登录面板
    private static JPanel createLoginPanel(JPanel mainPanel) {
        JPanel panel = new JPanel();
        panel.add(new JLabel("登录界面"));
        JButton loginButton = new JButton("登录");
        loginButton.addActionListener(e -> {
            // 点击登录按钮,切换到主界面
            ((CardLayout) mainPanel.getLayout()).show(mainPanel, "HOME");
        });
        panel.add(loginButton);
        return panel;
    }
    // 创建主界面
    private static JPanel createHomePanel(JPanel mainPanel) {
        JPanel panel = new JPanel();
        panel.add(new JLabel("欢迎来到主界面!"));
        JButton logoutButton = new JButton("退出");
        logoutButton.addActionListener(e -> {
            // 点击退出按钮,切换回登录界面
            ((CardLayout) mainPanel.getLayout()).show(mainPanel, "LOGIN");
        });
        panel.add(logoutButton);
        return panel;
    }
}

使用 JavaFX (切换 Scene)

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class SceneSwitchExample extends Application {
    @Override
    public void start(Stage primaryStage) {
        // 场景1:登录界面
        StackPane loginPane = new StackPane();
        Button loginButton = new Button("登录");
        loginPane.getChildren().add(loginButton);
        Scene loginScene = new Scene(loginPane, 300, 200);
        // 场景2:主界面
        StackPane homePane = new StackPane();
        Button logoutButton = new Button("退出");
        homePane.getChildren().add(logoutButton);
        Scene homeScene = new Scene(homePane, 300, 200);
        // 登录按钮事件:切换到主界面
        loginButton.setOnAction(e -> primaryStage.setScene(homeScene));
        // 退出按钮事件:切换回登录界面
        logoutButton.setOnAction(e -> primaryStage.setScene(loginScene));
        primaryStage.setTitle("场景切换示例");
        primaryStage.setScene(loginScene); // 初始显示登录界面
        primaryStage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }
}

打开一个新窗口

使用 Java Swing

// 在某个按钮的 ActionListener 中
JButton openNewWindowButton = new JButton("打开新窗口");
openNewWindowButton.addActionListener(e -> {
    JFrame newFrame = new JFrame("新窗口");
    newFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // 只关闭当前窗口
    newFrame.setSize(200, 150);
    newFrame.add(new JLabel("这是一个新窗口!"));
    newFrame.setVisible(true);
});

使用 JavaFX

// 在某个按钮的 EventHandler 中
Button openNewWindowButton = new Button("打开新窗口");
openNewWindowButton.setOnAction(e -> {
    Stage newStage = new Stage();
    newStage.setTitle("新窗口");
    StackPane newPane = new StackPane();
    newPane.getChildren().add(new Label("这是一个新窗口!"));
    newStage.setScene(new Scene(newPane, 200, 150));
    newStage.show();
});

Android 移动应用

在 Android 中,跳转指的是从一个 Activity(屏幕)导航到另一个 Activity

使用显式 Intent (跳转到同一个应用内的已知 Activity)

这是最基本的方式。

// 在当前 Activity 的某个方法中,例如按钮点击事件
Button navigateButton = findViewById(R.id.navigate_button);
navigateButton.setOnClickListener(v -> {
    // 1. 创建一个 Intent 对象
    // 参数1: 上下文 (Context)
    // 参数2: 目标 Activity 的 class 对象
    Intent intent = new Intent(MainActivity.this, SecondActivity.class);
    // 2. 启动 Activity
    startActivity(intent);
});

使用隐式 Intent (跳转到其他应用或系统组件)

打开一个网页、拨打电话、发送邮件等。

// 打开一个网页
Button openWebButton = findViewById(R.id.open_web_button);
openWebButton.setOnClickListener(v -> {
    Uri webpage = Uri.parse("https://www.google.com");
    Intent intent = new Intent(Intent.ACTION_VIEW, webpage);
    startActivity(intent);
});
// 拨打电话
Button callButton = findViewById(R.id.call_button);
callButton.setOnClickListener(v -> {
    Uri number = Uri.parse("tel:123456789");
    Intent intent = new Intent(Intent.ACTION_DIAL, number);
    startActivity(intent);
});

使用 Jetpack Navigation Component (现代 Android 开发推荐)

对于复杂的 App,使用 Navigation Component 可以更轻松、更安全地管理页面跳转,它能正确处理返回栈、传递参数、处理深链接等。

基本用法

  1. res/navigation/ 目录下创建一个导航图 (nav_graph.xml)。
  2. 在图中定义你的 Fragment(或 Activity)作为目标,并绘制它们之间的连接线(动作 Action)。
  3. 在代码中获取 NavController 并调用 navigate() 方法。
// 在 Fragment 或 Activity 中
NavController navController = Navigation.findNavController(view); // 或 getActivity().getNavController()
// 通过 ID 导航
navController.navigate(R.id.action_firstFragment_to_secondFragment);
// 传递参数
Bundle args = new Bundle();
args.putString("user_id", "123");
navController.navigate(R.id.action_firstFragment_to_secondFragment, args);

应用场景 跳转类型 关键技术/方法 特点
Web 后端 客户端跳转 (Redirect) response.sendRedirect() / return "redirect:..." URL改变,两次请求,可跳转外部
服务器端跳转 (Forward) request.getRequestDispatcher().forward() / 返回视图名 URL不变,一次请求,共享request数据
桌面应用 界面切换 Swing: CardLayout / JavaFX: 切换 Scene 在同一窗口内切换视图,用户体验流畅
新窗口 Swing: 新 JFrame / JavaFX: 新 Stage 打开独立的窗口
Android 应用 Activity 跳转 Intent (显式/隐式) 应用内或跨应用导航
现代导航 Jetpack Navigation Component 管理返回栈,传递参数,更安全可靠

请根据你正在开发的项目类型,选择最适合的跳转方式。

分享:
扫描分享到社交APP
上一篇
下一篇