CheckServlet类与OutputServlet类之间为请求转发关系。在web.xml文件中,为CheckServlet映射的URL为"/check",为OutputServlet映射的URL为"/outout"。

public class CheckServlet extends HttpServlet{

public void service(HttpServletRequest request,

HttpServletResponse response)throws ServletException,IOException{

String username = request.getParameter("username");

String message = null;

if(username == null){

message = "Please input username.";

}else{

message = "Hello," + username;

}

// request.setAttribute("msg",message);

// servletContext context = getServletContext();

RequestDispatcher dispatcher =

request.getRequestDispatcher ("output");

PrintWriter out = response.getWriter();

out.println("Output from CheckServlet before forwarding request");

System.out.println(

"Output from CheckServlet before forwarding request");

// out.close();

dispatcher.forward(request,response);

out.println("Output from CheckServlet after forward request.");

System.out.println(

"Output from CheckServlet after forwarding request.");

}

}

public class OutputServlet extends HttpServlet{

public void service(HttpServletRequest request,

HttpServletResponse response)thrwos ServletException,IOException{

String message = (String)request.getAttribute("msg");

PrintWriter out = response.getWriter();

out.println(message);

out.close();

}

}

CheckServlet先检查客户端是否提供了username请求参数,再根据此生成一条消息,用变量message表示,接下来把这条消息作为属性保存到ServletRequest对象中,再把请求转发给OutputServlet。与请求转发相关的代码为:

RequestDispatcher dispatcher = request.getRequestDispatcher("output");

dispatcher.forward(request,response);

以上dispatcher.forward(request,response)方法的处理流程如下。

●  清空用于存放响应正文数据的缓冲区。

●  如果目标组件为Servlet或JSP,就调用它们的service()方法,把该方法产生的响应结果发送到客户端;如果目标组件为文件系统中的静态HTML文档,就读取文档中的数据并把它发送到客户端。

转发流程图

从Dispatcher.forward(request,response)方法的处理流程可以看出,请求转发具有以下特点。

由于forward()方法先清空用于存放响应正文数据的缓冲区,因此Servlet源组件生成的响应结果不会被发送到客户端,自由目标组件生成的响应结果才会被发送到客户端。

如果源组件在进行请求转发之前,已经提交了响应结果(例如调用ServletResponse的flushBuffer()方法,或者调用与ServletResponse关联的输出流的close()方法),那么forward()方法会抛出IllegalStateException。为了避免该异常,不应该在源组件中提交响应结果。

案例中的OutputServlet类作为转发目标组件,先从ServletRequest对象中读取msg属性,然后把它作为响应结果发送到客户端。下面按照如下步骤演示本案例:

1.通过浏览器访问http://localhost:8080/helloapp/check,其中helloapp是项目名称,/check是请求路径,浏览器中会出现"Please input username"。

CheckServlet负责生成消息,而OutputServlet负责把消息发送给客户端。由此可见,CheckServlet与OutputServlet既分工明确,各行其职,又紧密协作,来响应同一个客户请求。

CheckServlet在调用dispatcher.forward(request,response)方法之前和之后,都试图向浏览器以及服务器的控制台输出一些数据:

out.println("Output from CheckServlet before forwarding request");

System.out.println("Output from CheckServlet before forwarding request");

dispatcher.forward(request,response);

out.println("Output from CheckServlet after forward request.");

System.out.println("Output from CheckServlet after forwarding request.");

从浏览器中显示的页面可以看出,CheckServlet作为源组件,它所生成的响应结果不会被发送到客户端。

此外,在Tomcat服务器的控制台,会显示调用forward()方法之前及之后的System.out.println()语句的打印结果。由此可见,在Servlet源组件中调用forward()方法之后的代码也会被执行。

2.修改CheckServlet类的代码,在CheckServlet类中调用forward()方法之前先关闭输出流:

out.close();

dispatcher.forward(request,response);

再次通过浏览器访问CheckServlet,浏览器端仅接收到了由CheckServlet输出的内容:

Output from CheckServlet before forward request;

这是因为CheckServlet的out.close()方法先把CheckServlet输出的内容提交给客户端,然后再关闭输出流。接下来调用forward()方法会抛出异常。

IT兄弟连 JavaWeb教程 请求转发案例的更多相关文章

  1. IT兄弟连 JavaWeb教程 请求重定向案例

    Check2Servlet类与Output2Servlet类之间为请求转发关系.在web.xml文件中,为Check2Servlet映射的URL为"/check2",为Output ...

  2. IT兄弟连 JavaWeb教程 Servlet转发

    Servlet对象由Servlet容器创建,并且Servlet对象的service()方法也由容器调用,一个Servlet对象可否直接调用另一个Servlet对象的service()方法呢?答案是否定 ...

  3. IT兄弟连 JavaWeb教程 JSP经典案例

    案例需求:定义一个javaBean叫XdlUser,有四个字段int id.String name.int age.double salary.写一个jsp页面,在页面中构建一个列表对象,里面存放几个 ...

  4. JavaWeb中请求转发和请求重定向的区别

    针对于JavaWeb中请求与重定向的一个cheatsheep: 1.转发 1)完成一次转发,用户浏览器发送一次请求 2)转发之后,浏览器URL地址栏不改变(服务器帮忙完成) 3)请求域中数据不丢失 4 ...

  5. IT兄弟连 JavaWeb教程 JSP内置对象1

    JSP内置对象定义 JSP提供了由容器实现和管理的内置对象,也可以称之为隐含对象,这些内置对象不需要通过JSP页面编写来实例化,在所有的JSP页面中都可以直接使用,它们起到了简化页面的作用,JSP的内 ...

  6. IT兄弟连 JavaWeb教程 JSP静态包含和动态包含的区别

    JSP静态包含(<%@ include>和JSP动态包含<jsp:include>同样都可以用来包含文件,但是他们之间是存在很大差别的.下面将对include指令与includ ...

  7. IT兄弟连 JavaWeb教程 JSP动作指令

    JSP动作指令语法 JSP动作指令语法格式如下: <jsp:动作名 属性名1="属性值1" 属性名2="属性值2" ... %> JSP具体动作指令 ...

  8. IT兄弟连 JavaWeb教程 EL与JSTL表达式经典案例

    案例需求:使用MVC模式编写一个程序,当发起一个deptList.do请求时,在servlet中准备一个部门列表对象,把这个列表对象放入request作用域中转发到deptlist.jsp,使用JST ...

  9. IT兄弟连 JavaWeb教程 JSP内置对象经典案例

    案例需求:使用MVC模式编写一个程序当发起一个deptList.do请求时在servlet中准备一个部门列表对象,把这个列表对象放入request作用域中,然后转发到deptlist.jsp,使用js ...

随机推荐

  1. android-problem——remount of /system failed: Read-only file system

    adb remount后仍旧不能对system进行读写.需要进行adb disable-verity 在Android6.0 (Android M)userdebug版本上(eng版本不存在该问题), ...

  2. 这样看ACM是不是更好?

    如果搞ACM只是为了拿奖,为了保研,这样太功利,整个过程都会变得没意思.我说过我同时看中过程和结果. 其实ACM解题也不是那么没意思,每次AC都有一种非常棒的成就感,每个题目就像是一个解谜游戏,完成了 ...

  3. 把握linux内核设计思想(五):下半部机制之工作队列及几种机制的选择

    [版权声明:尊重原创.转载请保留出处:blog.csdn.net/shallnet,文章仅供学习交流,请勿用于商业用途]         工作队列是下半部的第二种将工作推后运行形式.和软中断.task ...

  4. mysql 环境变量之 group_concat_max_len

    今天使用mysql group_concat()函数,对查询的数据进行字符串连接操作. 不过由于查询的结果较多,连接后的结果很长导致不能完全显示. 查询手册发现如下说明: (先说说group_conc ...

  5. PyOpenGL下GlutBitmapCharacter的替代

    虽然pyinstaller支持pyopengl,但是调用GLUT之后,在其它电脑上面运行就会出现错误,索性按照之前C#上面的办法,把字体数据和函数用python重写 fontData.py #! /u ...

  6. C语言socket send()数据缓存问题

    send()函数默认情况下会使用Nagle算法.Nagle算法通过将未确认的数据存入缓冲区直到积攒到一定数量一起发送的方法.来降低主机发送零碎小数据包的数目.所以假设send()函数发送数据过快的话, ...

  7. Linq To Sql进阶系列(六)用object的动态查询与保存log篇

    动态的生成sql语句,根据不同的条件构造不同的where字句,是拼接sql 字符串的好处.而Linq的推出,是为了弥补编程中的 Data != Object 的问题.我们又该如何实现用object的动 ...

  8. MapReduce算法形式五:TOP—N

    案例五:TOP—N 这个问题比较常见,一般都用于求前几个或者后几个的问题,shuffle有一个默认的排序是正序的,但如果需要逆序的并且暂时还不知道如何重写shuffle的排序规则的时候就用以下方法就行 ...

  9. 数据结构之 图论---图的深度遍历( 输出dfs的先后遍历序列 )

    图的深度遍历 Time Limit: 1000MS Memory limit: 65536K 题目描述 请定一个无向图,顶点编号从0到n-1,用深度优先搜索(DFS),遍历并输出.遍历时,先遍历节点编 ...

  10. re(正则表达式)模块

    一.最常用的匹配语法 re.match 从头开始匹配 re.search 匹配包含 re.findall 把所有匹配到的字符放到以列表中的元素返回 re.split  以匹配到的字符当做列表分隔符 r ...