标签:
HttpServletRequest
----------------------------------------------------------------
(4)请求分派
Servlet API中定义了一个RequestDispatcher接口,俗称请求分派器。
它有两个方法
forward(ServletRequest request,ServletResponse response)
include(ServletRequest request,ServletResponse response)
Forward()方法用于将请求转发到RequestDispatcher实例封装的资源;
Include()方法用于将RequestDispatcher实例封装的资源作为当前响应内容的一部分包含进来。
而获取RequestDispatcher实例也主要有两种。
调用ServletContext接口提供的getRequestDispatcher(String url)方法
调用ServletRequest接口提供的getRequestDispatcher(String url)方法
区别:
调用ServletContext接口提供的getRequestDispatcher(String url)方法必须是绝对路径
调用ServletRequest接口提供的getRequestDispatcher(String url)方法可以是相对路径,也可以是绝对路径。
举例:
创建一个Servlet(demo1.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;
public class demo1 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
//提交到demo2、
out.println("<form method=‘get‘ action=‘/demo/demo2‘>");
out.println("用户名:<input type=‘text‘ name=‘username‘ /><br/>");
out.println("密 码:<input type=‘password‘ name=‘pass‘ /><br/>");
out.println("<input type=‘submit‘ value=‘提交‘ ");
out.println("</form>");
}
}
创建一个Servlet(demo2.java),代码如下:
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
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;
public class demo2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("utf-8");
//PrintWriter out = response.getWriter();
//获取请求分派器
RequestDispatcher dispatcher = request.getRequestDispatcher("demo3");
//将请求转发至指定路径的资源
dispatcher.forward(request, response);
}
}
创建Servlet(demo3.java),代码如下:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class demo3 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
request.setCharacterEncoding("utf-8");
//获得用户输入的用户名
String name = request.getParameter("username");
out.println(name+"已经请求转发到demo3了");
}
}
原理:
当浏览器发起一次http请求时,Web服务器将demo2请求转发给第二个资源(即demo3),demo3将一次响应返回给服务器。
当调用这条语句时,并没有直接转发给浏览器,而是转发给Web服务器,Web服务器再调用。请求转发是发生在Web服务器。
效果如下:
在demo1中输入用户名和密码;
跳转的页面是demo2 ,显示的内容却是demo3的效果
这种情况下浏览器只发出一次请求,服务器也只返回一次响应。浏览器地址栏的URI是demo2,但服务器却只用demo3来进行响应的。在demo3中也可以获取客户端请求demo2是发送的参数数据。
(5)利用请求域属性传递对象数据
HttpServletRequest接口中提供了几个方法用来操作请求实例中存储的对象。
(1)setAttribute(String name,Object obj);
//将对象存储进HttpServletRequest实例中
(2)getAttribute(String name);
//检索存储在HttpServletRequest实例中的对象。
(3)getAttributeNames();
(4)removeAttribute(String name);
这种存储在HttpServletRequest中的对象称之为请求域属性,属于同一请求过程的多个处理模块之间可以通过请求域属性来传递对象数据,如通过请求转发的两个Servlet之间就可以通过请求域属性来传递对象数据,但通过重定向的两个Servlet之间就不能通过请求域属性来传递对象数据。
在请求分派的例子上,demo1不用改变。
demo2.java的代码如下:
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;
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;
public class demo2 extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
request.setCharacterEncoding("utf-8");
//PrintWriter out = response.getWriter();
//将一个字符串存放在请求域属性中
String str = "hello world!";
request.setAttribute("str",str);
RequestDispatcher dispatcher = request.getRequestDispatcher("demo3");
dispatcher.forward(request, response);
}
}
demo3.java代码如下:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class demo3 extends HttpServlet {
protected void doGet(HttpServletRequestrequest, HttpServletResponseresponse)throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
PrintWriterout =response.getWriter();
request.setCharacterEncoding("utf-8");
Stringname =request.getParameter("username");
//从请求域属性中取出str这个对象。
String str = (String)request.getAttribute("str");
out.println(name+"已经请求转发到demo3了<br/>");
out.println("我在demo3获取demo2请求域属性的值为:&"+str);
}
}
依然输出用户名和密码,提交。
效果如下:
request中的attribute只在一次请求有效。
不可以通过sendRedirect方式取得域对象中值,因为域对象只能在一次请求有效,sendRedirect重定向后request和response都是全新的。
//因为是在Web服务器中发生的,所以只需要填写资源名
request.getRequestDispatcher(“/资源名URI”).forward(request,response);
//因为发生在浏览器,浏览器就得知道要重定向到哪个Web应用
response.sendRedirect(“/Web应用/Web资源”);
用处:
通常在Servlet中处理客户请求,然后把需要返回给用户的动态数据利用请求域属性传递到JSP页面,在JSP页面中解析成HTML,在返回给客户端。
总结:重定向和请求分派(请求转发)的区别
虽然HttpServletRequest的sendRedirect()方法和RequestDispatcher的forward()方法都可以让浏览器获得另一个URL所指向的资源所做的响应,但两者的内部运行机制有着很大的区别。
(1)请求分派只能将请求转发给同一个Web应用的其他资源。
重定向不仅可以定向到当前Web应用的其他资源,也可以重定向到其他站点的资源上。
(2) 请求分派是在接收到客户端请求后通知服务器调用另一个Web资源,http状态码为307。
重定向是在接收到客户端请求后通知浏览器调用另一个Web资源,http状态码为302。
(3)重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改变,有初始的URL地址变成重定向的目标URL;
而请求转发过程结束后,浏览器地址栏保持初始的URL地址不变
(4)请求分派的发起者和被调用者之间共享相同的request实例和response实例,它们属于同一个“请求/响应“过程 ;
而重定向的发起者和被调用者使用各自的request实例和response实例,它们各自属于独立的“请求/响应”过程。
Java Web -- Servlet(13)HttpServletRequest详解(获取请求数据、请求分派、请求域)(2)
标签:
原文地址:http://blog.csdn.net/foces_18/article/details/51246522