请求转发与重定向
请求转发与重定向均是指的请求的跳转方式。用户提交请求需要访问服务端的资源 1, 而资源 1 又需要访问资源 2,那么由资源 1 向资源 2 的跳转,具有两种方式:请求转发与重 定向。
(1) 请求转发
请求转发是指,资源 1 在服务器内部,直接跳转到的资源 2,所以请求转发也称为服务 器内跳转。整个过程浏览器只发出一次请求,服务器只发出一次响应。所以,无论是资源 1 还是资源 2,整个过程中,只存在一次请求,即用户所提交的请求。所以,无论是资源 1 还 是资源 2,它们均可从这个请求中获取到用户提交请求时所携带的相关数据。
(2) 重定向
重定向是指,资源 1 需要访问资源 2,但并未在服务器内直接访问,而是由服务器自动 向浏览器发送一个响应,浏览器再自动提交一个新的请求,这个请求就是对资源 2 的请求。 对于资源 2 的访问,是先跳出了服务器,跳转到了客户端浏览器,再跳回到了服务器。所以 重定向又称为服务器外跳转。 整个过程中,浏览器共提交了两次请求,服务器共发送了两次响应。只不过,第一次响 应与第二次请求,对于用户来说是透明的,是感知不到的。用户认为,自己只提交了一次请 求,且只收到了一次响应。 这样的话,就出现了一个问题:资源 2 中是无法获取到用户提交请求中的数据的。它只 能获取到第二次请求中所携带的数据。
(3) 请求转发案例
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="login" method="post">
姓名:<input type="text" name="uname"/><br/>
坐标:<input type="text" name="uplace"/><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
LoginServlet.java
package com.orbit.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
//获取请求参数值
String name = request.getParameter("uname");
String place = request.getParameter("uplace");
//将请求参数值封装到域属性中
request.setAttribute("loginName",name);
request.setAttribute("loginPlace",place);
//请求转发
request.getRequestDispatcher("second").forward(request, response);
}
}
SecondServlet.java
package com.orbit.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/second")
public class SecondServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置响应体的内容类型
response.setContentType("text/html;charset=ISO-8859-1");
//setCharacterEncoding的作用其实就是修改setContentType的charset值
response.setCharacterEncoding("UTF-8");
//该页面也可以获取该请求的参数值
String name = request.getParameter("uname");
String place = request.getParameter("uplace");
//获取域属性值
String secondName = (String) request.getAttribute("loginName");
String secondPlace = (String) request.getAttribute("loginPlace");
//标准输出流
PrintWriter out = response.getWriter();
out.print("---请求的参数值---" + "<br/>" + "name = " + name + "<br/>" + "place = " + place + "<br/>");
out.print("---请求的域属性---" + "<br/>" + "name = " + secondName + "<br/>" + "place = " + secondPlace);
}
}
输出结果
(4) 重定向案例
index.html(同上)
Loginservlet.java
package com.orbit.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// request.setCharacterEncoding("UTF-8");
//获取请求参数值
String name = request.getParameter("uname");
String place = request.getParameter("uplace");
//将请求参数值封装到域属性
request.setAttribute("loginName",name);
request.setAttribute("loginPlace",place);
//请求转发
response.sendRedirect("second");
}
}
SecondServlet.java(同上)
输出结果:
(5) 重定向的数据传递
重定向时是无法将用户提交请求中的数据传递到重定向的资源的。若要向重定向的资源 中传递数据,则需要在重定向的请求地址后携带请求参数。
携带请求参数的形式为: 请求路径?参数名=值&参数名=值&„„
index.html
secondServlet.java
LoginServlet.java
package com.orbit.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
//获取请求参数值
String name = request.getParameter("uname");
name = new String(name.getBytes("UTF-8"),"ISO8859-1");
String place = request.getParameter("uplace");
place = new String(place.getBytes("UTF-8"),"ISO8859-1");
//将请求参数值封装到域属性
request.setAttribute("loginName",name);
request.setAttribute("loginPlace",place);
//请求转发
response.sendRedirect("second?loginName=" + name + "&loginPlace=" + place);
}
}
输出结果:
(6) 使用重定向到其他的应用(项目)
redirect-1/FirstServlet.java
package orbit;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/first")
public class FirstServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//重定向到另一个应用名为redirect-2的second页面
response.sendRedirect("/redirect-2/second");
}
}
redirect-1/SecondServlet.java
package orbit;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/second")
public class SecondServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.print("this is SecondServlet");
}
}
输出结果:
(7) 请求转发与重定向的区别
请求转发 | 重定向 |
---|---|
A、浏览器只发出一次请求,收到一次响应 | A、浏览器发出两次请求,接收到两次响应 |
B、请求所转发到的资源中可以直接获取到请求中所携带的数据 | B、重定向到的资源不能直接获取到用户提交请求中所携带的数据 |
C、浏览器地址栏显示的为用户所提交的请求路径 | C、浏览器地址栏显示的为重定向的请求路径,而非用户提交请求的路径。也正因为如此, 重定向的一个很重要作用是:防止表单重复提交 (即便刷新地址栏也不会提交到用户提交请求的路径) |
D、只能跳转到当前应用的资源中 | D、重定向不仅可以跳转到当前应用的其它资源,也可以跳转到到其它应用中资源 |
(8) 请求转发与重定向使用的情况
(1)若需要跳转到其它应用,则使用重定向。
(2)若是处理表单数据的 Servlet 要跳转到其它 Servlet,则需要选择重定向。为了防止表单重复提交。
(3)若对某一请求进行处理的 Servlet 的执行需要消耗大量的服务器资源(CPU、内存),此 时这个 Servlet 执行完毕后,也需要重定向。 (也是为了防止表单重复提交)
(4)其它情况,一般使用请求转发