开门见山
Servlet 应用包括 数据处理 和 重定向与请求转发。今儿我们唠唠重定向与数据转发
Servlet 处理完客户端请求的数据后,会给客户端一个响应,将请求相对应的结果给返回。
响应结果可以是一个由当前 Servlet 对象的 PrintWriter 输出流直接显示在输出页面上的信息,也可以是一个新的 URL 地址对应的信息。例如 HTML、JSP、Servlet 或是等等其他形式的 HTTP 地址。记住只要是 HTTP 地址就好。
那么怎么才能到达新的 URL 地址呢?
Servlet 主要通过两种方式:重定向和请求转发
一、重定向
重定向:由原请求地址重新定位到某个新地址,原有的请求失效,客户端浏览器地址栏由原地址变为新请求地址,客户端页面显示由原洁面变为新的请求返回的响应结果。
一个由请求 ServletA 到 ServletB 的重定向过程为:
· 客户端请求 ServletA
· 服务器查找 ServletA
· ServletA 重定向 ServletB 并将信息返回服务器
· 服务器重定向 ServletB 并将响应结果返回客户端
· 客户端 请求 ServletB
· 服务器 查找 ServletB
· ServletB 向服务器返回响应结果,即执行完毕
· 服务器向客户端返回响应结果
整个重定向过程包括客户端和服务器的两次请求和两次响应,其中第二次客户端的请求是由客户端自动发起的。
【语法】
location 参数就是重定向的新的 URL。
【示例】页面重定向
重定向到 /chapter02/index.jsp
sendRedirect() 方法不仅可以重定向到当前应用程序中的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,甚至是重定向到其他站点的资源。不过前提是你得知道 URL。
1)从一个 Servlet 请求重定向到另一个 Servlet
【代码】RedirectServlet.java
【代码】ResultServlet.java
【运行结果】
二、请求转发
请求转发 顾名思义 是指将请求再转发到其他地址,转发过程中使用的是同一个请求,转发后浏览器地址栏内容不变。
一个请求转发的过程(由请求 ServletA 到 ServletB 的转发过程)
· 客户端 向服务器端请求 ServletA
· 服务器端查找 ServletA
· ServletA 转发至 ServletB
· ServletB 将执行结果返回给服务器
· 服务器向客户端响应结果
请求转发的过程是发送在服务器内部的,服务器只能从当前应用内部查找相应的转发资源,而不能转发到其他应用的资源。
请求转发使用 RequestDispatcher 接口中的 forward() 方法实现。
在 RequestDispatcher 接口中有两个方法:forward() 方法 和 include() 方法
· forward() 方法:将请求转发给其他资源
· include() 方法:将其他资源并入到当前请求中
RequestDispatcher 我们也多次强调这是一个接口,所以需要通过使用 HttpRequest 对象的 getRequestDispatcher() 方法来获取该接口的实例对象。
【语法】
【说明】
· path 参数用以指定转发的 URL,且只能是相对路径,从而表明不能转发到其他应用的资源
· request 和 response 参数取值为当前请求所对应的 HttpServletRequest 和 HttpServletResponse 对象
【示例】页面请求转发
请求转发中方法 getRequestDispatcher("/index.jsp") 和 重定向方法 sendRedirect("/chapter02/index.jsp"),他们两的 “/” 含义和用处是不一样的
在 getRequestDispatcher() 中相对路径的 “/” 表示当前应用程序的根目录
而 sendRedirect() 中相对路径的 “/” 表示整个 Web 站点的根目录
2)从一个 Servlet 请求转发到另一个 Servlet 的过程
【代码】ForwardServlet.java
【运行结果】
请求转发和重定向的最主要区别是:请求转发前后共享同一个请求对象,而重定向前后汇创建不同的请求对象。
3)通过重定向手段向 HttpServletRequest 对象中存取属性值
【代码】RedirectAttributeServlet.java
【代码】ResultAttributeServlet.java
【运行结果】
我们先将 attrobj 属性设置为 text, 在重定向后 重新获取 attrobj 的属性值,结果为获取不到。
可以很清晰的看出,通过重定向方式无法获得重定向前请求对象中的属性值。
4)通过请求转发手段向 HttpServletRequest 对象中存取属性值
【代码】ForwardAttributeServlet.java
【运行结果】
明显可以看到和重定向的区别,通过请求转发方式可以获得转发前请求对象中的属性值
请求转发和重定向的区别:
· 转发只能将请求转发给同一个Web 应用中的组件;而重定向不仅可以重定向到应用程序中的其他资源,还可以重定向到同一个站点上的其他应用程序中的资源,或者重定向到其他站点的资源。
· 重定向的访问过程结束后,浏览器地址栏中现实的 URL 会发生改变,由初始的 URL 地址变成重定向的目标 URL ;
而请求转发过程结束后,浏览器地址栏保持初始 URL 地址不变
· 重定向对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个 URL 的访问请求;
请求转发在服务器端内部将请求转发给另一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为
· 请求转发调用者与被调用者之间共享相同的请求对象和响应对象,他们属于同一个访问请求和响应过程;
而重定向调用者与被调用者使用各自的请求对象和响应对象,他们属于两个独立的访问请求和响应过程。
头秃,不过这块还蛮好理解的。一个是 重定向,另一个是 请求转发
最后代码附上
【RedirectServlet.java】
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;
/**
* Servlet implementation class RedirectServlet
*/
@WebServlet("/RedirectServlet")
public class RedirectServlet extends HttpServlet {
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("没重定向");
//进行重定向
response.sendRedirect(request.getContextPath() + "/ResultServlet");
System.out.println("重定向完毕");
}
}
【ResultServlet.java】
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;
/**
* Servlet implementation class ResultServlet
*/
@WebServlet("/ResultServlet")
public class ResultServlet extends HttpServlet {
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置响应到客户端的文本类型为 HTML
response.setContentType("text/html;charset=UTF-8");
//获取输出流
PrintWriter out = response.getWriter();
//输出相应结果
out.println("<p>重定向和请求转发的结果页面</p>");
}
}
【ForwardServlet.java】
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ForwardServlet
*/
@WebServlet("/ForwardServlet")
public class ForwardServlet extends HttpServlet {
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("请求转发前:");
RequestDispatcher dispatcher = request.getRequestDispatcher("/ResultServlet");
dispatcher.forward(request, response);
System.out.println("请求转发完毕");
}
}
【RedirectAttributeServlet.java】
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;
/**
* Servlet implementation class RedirectAttributeServlet
*/
@WebServlet("/RedirectAttributeServlet")
public class RedirectAttributeServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 把 attrobj 属性值 test 存储到 request 对象中
request.setAttribute("attrobj", "test");
System.out.println("重定向前:");
// 进行重定向
response.sendRedirect(request.getContextPath() + "/ResultAttributeServlet");
System.out.println("重定向后");
}
}
【ResultAttributeServlet.java】
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;
/**
* Servlet implementation class ResultAttributeServlet
*/
@WebServlet("/ResultAttributeServlet")
public class ResultAttributeServlet extends HttpServlet {
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 设置响应到客户端的文本类型为 HTML
response.setContentType("text/html;charset=UTF-8");
// 从 request 对象中获取 attrobj 属性值
String attrobj = (String)request.getAttribute("attrobj");
// 获取输出流
PrintWriter out = response.getWriter();
// 输出响应结果
out.println("<p>重定向和请求转发的结果页面</p>");
out.println("读取的 request 对象的 attrobj 属性值为:" + attrobj);
}
}
【ForwardAttributeServlet.java】
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ForwardAttributeServlet
*/
@WebServlet("/ForwardAttributeServlet")
public class ForwardAttributeServlet extends HttpServlet {
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 将 attrobj 属性值 test 存储到 request 对象中
request.setAttribute("attrobj", "test");
System.out.println("请求转发前");
RequestDispatcher dispatcher = request.getRequestDispatcher("/ResultAttributeServlet");
dispatcher.forward(request, response);
System.out.println("请求转发后");
}
}