java学习之Servlet请求转发之RequestDispatcher

来源:互联网 发布:mysql命令大全查询 编辑:程序博客网 时间:2024/06/10 19:38

转发的原理:

Servlet请求转发原理图

 

 

图片来自:http://blog.sina.com.cn/s/blog_4a157f470100a86y.html?retcode=0

 

浏览器将请求发送至servlet容器后,相应的组件获取到这个请求,然后在其内部将这个请求转发(request, response)给另外一个组件2,然后有组件2来响应浏览器的请求,但是此时浏览器上看到的仍然是组件1的地址。

在转发中,实际上转发的只有request,返回个浏览器的response的内容仍然是组件1中的设置。看下面代码:

 

IncludingServlet.java

[java] view plaincopy
  1. import java.io.IOException;  
  2. import java.io.PrintWriter;  
  3. import javax.servlet.RequestDispatcher;  
  4. import javax.servlet.ServletException;  
  5. import javax.servlet.http.HttpServlet;  
  6. import javax.servlet.http.HttpServletRequest;  
  7. import javax.servlet.http.HttpServletResponse;  
  8.   
  9. public class IncludingServlet extends HttpServlet {  
  10.     @Override  
  11.     protected void service(HttpServletRequest req, HttpServletResponse resp)  
  12.             throws ServletException, IOException {  
  13.         resp.setContentType("text/html;charset=UTF-8");  
  14.           
  15.         PrintWriter out = resp.getWriter();  
  16.         String china = "中国";  
  17.           
  18.         RequestDispatcher requestDispatcher = this.getServletContext().getRequestDispatcher(  
  19.                 "/IncludedServlet?p1=" + china);  
  20.           
  21.         out.println("Before including<br />");  
  22.         requestDispatcher.include(req, resp);  
  23.         out.println("After including<br />");  
  24.     }  
  25. }  

 

IncludedServlet.java

[java] view plaincopy
  1. import java.io.IOException;  
  2. import java.io.PrintWriter;  
  3. import javax.servlet.ServletException;  
  4. import javax.servlet.http.HttpServlet;  
  5. import javax.servlet.http.HttpServletRequest;  
  6. import javax.servlet.http.HttpServletResponse;  
  7.   
  8. public class IncludedServlet extends HttpServlet {  
  9.     @Override  
  10.     protected void service(HttpServletRequest req, HttpServletResponse resp)  
  11.             throws ServletException, IOException {  
  12.         resp.setContentType("text/html;charset=UTF-8");  
  13.         resp.setCharacterEncoding("UTF-8");  
  14.         PrintWriter out = resp.getWriter();  
  15.         out.println("中国<br />");  
  16.         out.println("URI:" + req.getRequestURI() + "<br />");  
  17.         out.println("QueryString:" + req.getQueryString() + "<br />");  
  18.         out.println("Parameter p1:" + req.getParameter("p1") + "<br />");  
  19.     }  
  20. }  
 

*代码源自《Java Web开发内幕——核心基础》

 

在web.xml文件中注册上面两个servlet,运行tomcat,在浏览器中输入对IncludingSerlvet的请求,得到结果:

这里面正确地显示出了“中国”两个UTF-8编码的字符,但看上面的代码可以发现,两段代码都对response进行了设置文字编码操作,那究竟是哪一个设置起的作用?

尝试将IncludingServlet.java中的response的操作注释掉,再看结果,如下:

此时中国两个字显示成了乱码,这就说明了被转发的Servlet不能改变响应消息的状态码和响应头,同样,无法修改HttpServletRespnse对象中的信息。同样也看到了虽然IncludingServlet转发给了IncludedServlet,但是浏览器地址栏显示的还是调用者IncludingServlet的URI。

 

再来讨论另外一种情况,在servlet文件目录下新建一个chinese.html文件,内容为:

[xhtml] view plaincopy
  1. <s>这是一句被划掉的文字<s>  

修改IncludingServlet.java文件的代码如下:

[java] view plaincopy
  1. import java.io.IOException;  
  2. //import java.io.PrintWriter;  
  3. import javax.servlet.RequestDispatcher;  
  4. import javax.servlet.ServletException;  
  5. import javax.servlet.http.HttpServlet;  
  6. import javax.servlet.http.HttpServletRequest;  
  7. import javax.servlet.http.HttpServletResponse;  
  8.   
  9. public class IncludingServlet extends HttpServlet {  
  10.     @Override  
  11.     protected void service(HttpServletRequest req, HttpServletResponse resp)  
  12.             throws ServletException, IOException {  
  13.         //resp.setContentType("text/html;charset=UTF-8");  
  14.         //resp.setCharacterEncoding("UTF-8");  
  15.           
  16.         //PrintWriter out = resp.getWriter();  
  17.         //String china = "中国";  
  18.           
  19.         //RequestDispatcher requestDispatcher = this.getServletContext().getRequestDispatcher(  
  20.         //      "/IncludedServlet?p1=" + china);  
  21.           
  22.         RequestDispatcher requestDispatcher = this.getServletContext().getRequestDispatcher(  
  23.                 "/chinese.html");  
  24.           
  25.         //out.println("Before including<br />");  
  26.         requestDispatcher.include(req, resp);  
  27.         //out.println("After including<br />");  
  28.     }  
  29. }  

 

运行结果如下:

如果直接访问这个页面,得到如下结果:

为什么经过转发以后就不能解析html内容了呢?即,为什么直接访问html页面所得到的相映消息中包好Content-Type字段而通过IncludingServlet转发的则不包含呢?

解释是,凡是在web.xml中找不到匹配<servlet-mapping>元素的URL请求,也就是其他Serlvet都不处理的请求,都将交给tomcat的一个缺省servlet来处理,客户端对静态html的访问时间上就是在调用这个缺省servlet来完成响应的。所以,调用一个html和调用一个servlet本质上是一样的。

故在上面例子中,在IncludingServlet.java中加上

[java] view plaincopy
  1. resp.setContentType("text/html";charset=UTF-8");  

这样就能得到正确的输出了。

 

在一个问题,ServletContext中的getRequestDispatcher方法和Request中的getRequestDispatcher方法的不同之处:ServletContext中的getRequestDispatcher方法在指定URI时不能使用相对地址,而Request中的getRequestDispatcher方法可以。


转载地址:http://blog.csdn.net/baoyiming1991/article/details/5972989

0 0
原创粉丝点击