JavaWEB-(二十三)转发与重定向

本文最后更新于:May 13, 2023 pm

Servlet中的页面跳转可以通过转发或者重定向来实现。转发是指一个请求处理器(ServletA)将请求交给另一个处理器处理(ServletB),再将结果返回。重定向是请求处理器接收到请求时,不处理请求而是告诉用户浏览器应该发送另外的请求,然后用户浏览器再跳转到被告知的请求。

目录

1.转发(request)

转发的作用在服务器端,将请求发送给服务器上的其他资源,已达到共同完成一次请求的处理。

1.1 页面跳转

request.getRequestDispatcher(“/目标URL-pattern”).forward(request,response);

使用forward跳转时,是在服务器内部跳转,地址栏不发生变化,这一点与重定向不同。并且是属于同一次请求。即不管跳转几下,都是属于同一次请求。如图。

示例:

A.java 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.tothefor.Servlet;


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.util.ArrayList;
import java.util.List;

/**
* @Author DragonOne
* @Date 2021/8/20 22:11
*/
@WebServlet(value = "/a")
public class A extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("/b").forward(req,resp);
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}

B.java 代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.tothefor.Servlet;

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;

/**
* @Author DragonOne
* @Date 2021/8/20 22:15
*/
@WebServlet(value = "/b")
public class B extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("B页面");
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}

最后在控制台上可以看见打印的结果。并且可以发现,在地址栏中访问A,跳转后并没有变成 B

1.2 数据传递

因为forward表示一次请求,是在服务器内部跳转,所以可以共享同一次 request 作用域中的数据。

  • request作用域:拥有存储数据的空间,作用范围是一次请求有效(一次请求可以经过多次转发)。可以将数据存入request中,并且可以在一次请求过程中的任何位置进行获取。而且可以传递任何数据类型(基本数据类型、对象、数组、集合等)。

1.2.1 存数据

request.setAttribute(key,value);

以键值对形式存储在 request 作用域中。其中key为String类型,value为Object类型。key任意取。

1.2.2 取数据

request.getAttribute(key);

通过String类型的key访问Object类型的value,需要进行类型强转。

示例:

A.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.tothefor.Servlet;


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.util.ArrayList;
import java.util.List;

/**
* @Author DragonOne
* @Date 2021/8/20 22:11
*/
@WebServlet(value = "/a")
public class A extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
List<String> list = new ArrayList<>();
list.add("qwer");
list.add("asdf");
list.add("zxcv");
req.setAttribute("lists",list);
req.getRequestDispatcher("/b").forward(req,resp);
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}

B.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.tothefor.Servlet;

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;
import java.util.List;

/**
* @Author DragonOne
* @Date 2021/8/20 22:15
*/
@WebServlet(value = "/b")
public class B extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("B页面");
List<String> list = (List<String>) req.getAttribute("lists");
for(String it : list){
System.out.println(it);
}
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}

1.3 转发的特点

  1. 转发是服务器行为。
  1. 转发是浏览器只做了一次访问请求。
  1. 转发浏览器地址不变。
  1. 转发的两次跳转之间传输的信息不会丢失。
  1. 转发只能将请求转发给同一个Web应用中的组件。即在同一个Web项目下使用。

2.重定向(response)

重定向作用在客户端,客户端将请求发送给服务器后,服务器相应给客户端一个新的请求地址,客户端再重新发生新请求。这样一来,地址栏的地址就会发生变化,这一点与转发不同。

2.1 页面跳转

response.sendRedirect(“URL”); 这里的URL需要和转发中的区别开。这里的URL需要指明的哪个项目下的哪个资源。

URL:统一资源标识符,用来表示服务器中定位一个资源,资源在Web项目中的路径。

2.2 数据传递

sendRedirect 跳转时,地址栏发生变化,代表客户端重新发送的请求。属于两次请求。

  1. response 没有作用域,两次 request 请求中的数据无法共享。
  1. 传递数据:通过URL的拼接进行数据传递(如:”/Test1_war_exploded/b?username=loong”);
  1. 获取数据:request.getParameter(“username”); 这种方法只能获取String类型的数据。即,重定向只能传递String类型的数据,并且是明文传递的,因为是拼接在URL后面的。

示例:

A.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.tothefor.Servlet;


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.util.ArrayList;
import java.util.List;

/**
* @Author DragonOne
* @Date 2021/8/20 22:11
*/
@WebServlet(value = "/a")
public class A extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("/Test1_war_exploded/b?username=loong");
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}

B.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.tothefor.Servlet;

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;
import java.util.List;

/**
* @Author DragonOne
* @Date 2021/8/20 22:15
*/
@WebServlet(value = "/b")
public class B extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("B页面2");
String name = req.getParameter("username");
System.out.println(name);
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}

2.3 重定向特点

  1. 重定向是客户端行为。
  1. 重定向是浏览器做了至少两次的访问请求。
  1. 重定向的浏览器地址会改变。
  1. 重定向两次跳转之间传输的信息会丢失(request范围)。
  1. 重定向可以指向任何的资源,包括当前应用程序中的其他资源、同一个站点上的其他应用程序中的资源、其他站点资源。

3.总结

当两个Servlet需要传递数据时,选择forward转发。不建议使用sendRedirect进行传递。

但推荐使用转发,不使用重定向,即使是传递的数据是String类型的。因为重定向的数据传递方式是明文,不安全。