1 / 69

第八讲

第八讲. 课  题  JAVA 服务器小程序( ServLet )之 Servlet 链、编程应用 目的要求 掌握 Servlet 链的含义及编程应用   教学重点  ServLet 链的构建与 Shtml 的使用 教学难点 ServLet 链的构建 教学课时 4 (含 2 课时上机) 教学方法 讲解、示例与启发式教学相结合  . 教学内容和步骤 8.1 Servlet 链 8.1.1 什么是 servlet 链

holli
Download Presentation

第八讲

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第八讲

  2. 课  题 JAVA服务器小程序(ServLet)之Servlet链、编程应用课  题 JAVA服务器小程序(ServLet)之Servlet链、编程应用 目的要求 掌握Servlet链的含义及编程应用   教学重点 ServLet链的构建与Shtml的使用 教学难点 ServLet链的构建 教学课时 4(含2课时上机) 教学方法 讲解、示例与启发式教学相结合  

  3. 教学内容和步骤 8.1 Servlet链 8.1.1 什么是servlet链 Servlet链,它是JvavServer体系结构的高级特征之一, 与UNIX和DOS命令中的管道类似,你也可以将多个servlet以特定顺序链接起来。在servlet链中,一个servlet的输出被当作下一个servlet的输入,而链中最后一个servlet的输出被返回到浏览器。

  4. 8.1.2表过滤器(Table Filter)  我们以表过滤器看看如何编写一个可以被用于链接的servlet,这个表过滤器servlet将分析另一个servlet的输出,查找含有特殊表格式指令的HTML注释,这些指令包括表有多少列、是否显示表头等等。在该表格式指令之后的所有行将会被格式化成一个HTML表格。这样,链中的前一个servlet只要简单地将数据用逗号分割,数据就可以一行一行地直接输出了,而无须将这些数据格式化成HTML表格。同样,当你决定修改这个表格的格式时,你就不必修改产生数据的servlet,而直接修改这个表过滤器servlet就可以了。

  5.  这个表过滤器servlet实现了HTTP服务的方法。首先,它必须重复(echo)上一个servlet中设置的头信息。这些信息包括内容类型、调用的URL、远程主机等等。TableFilter.java显示了设置这些头信息的必要代码。 这个表过滤器servlet实现了HTTP服务的方法。首先,它必须重复(echo)上一个servlet中设置的头信息。这些信息包括内容类型、调用的URL、远程主机等等。TableFilter.java显示了设置这些头信息的必要代码。 例1:TableFilter.java package javaservlets.samples; import javax.servlet.*; import javax.servlet.http.*; import java.io.BufferedReader; import java.io.InputStreamReader; public class TableFilter extends HttpServlet {

  6. /**     * <p>Performs an HTTP service request     * @param req The request from the client     * @param resp The response from the servlet     */ public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, java.io.IOException {

  7. // Get all headers set by the previous servlet and echo them java.util.Enumeration e = req.getHeaderNames(); while (e.hasMoreElements()) { String header = (String)e.nextElement(); String value = req.getHeader(header); resp.setHeader(header, value); }

  8. // 如下述代码所示,接下来的步骤是取得一个可以从前一个servlet的输出流中讲读取数据的输入流,如果该输入流的内容类型是某种我们可以分析的类型(如HTML),我们就继续下一步骤;否则,我们就从输入流中读出所有字节并毫不修改地把它们写回浏览器。 // Get the input and output streams ServletInputStream in = req.getInputStream(); ServletOutputStream out = resp.getOutputStream(); // Only process if this is a recognized MIME type String type = req.getContentType();

  9. if (type.equals("text/html") || type.equals("text/table") || type.equals("application/x-www-form-urlencoded")) { resp.setContentType("text/html"); // Create a buffered reader that we can use to read // a single line at a time BufferedReader br = new BufferedReader(new InputStreamReader(in));

  10. boolean inTable = false; int tableCols = 0; boolean headerRow = false; // Read until no more data exists while (true) { String s = br.readLine(); // null indicates end of file if (s == null) { break; } // If we are in the middle of a table command, process // the line if (inTable) {

  11. // Search for the end of the table if (s.startsWith("<!--end table")) { out.println("</table></center>"); inTable = false; } else { // We've got a row of a table - format it s = formatRow(s, tableCols, headerRow); headerRow = false; }

  12. } else { // Search for the start of a tableif (s.startsWith("<!--table")) { int pos = s.indexOf("columns="); tableCols = 0; if (pos >= 0) { // Get the number of columns String cols = s.substring(pos + 8); int endPos = cols.indexOf(" "); if (endPos > 0) { cols = cols.substring(0, endPos); }

  13. tableCols = Integer.parseInt(cols); } // Get the header flag. If 'yes' the first // row of data is actually a header pos = s.indexOf("header="); if(pos >= 0) { String flag = s.substring(pos + 7); headerRow = flag.startsWith("yes"); } // If we have a valid number of columns, format // the table

  14. if (tableCols > 0) { out.println(s); s = "<center><table border>"; inTable = true; } }}out.println(s);} } else { // Unsupported MIME type; echo the contents unchanged

  15. while (true) { int b = in.read(); if (b == -1) { break; } out.write(b); } } out.close(); } /**    * <p>Formats the given line into a table row    */

  16. private String formatRow(String line, int cols, boolean header) { String s = "<tr>"; int pos = line.indexOf(","); int lastPos = 0; // Loop for each column for (int i = 0; i < cols; i++) { if (pos < 0) { pos = line.length(); } // Insert the proper HTML tag if (header) { s += "<th>"; }

  17. else { s += "<td>"; } // Find the next column data if (pos > 0) { s += line.substring(lastPos, pos); lastPos = pos; if (pos < line.length()) { lastPos = pos + 1; pos = line.indexOf(",", lastPos); } else {

  18. pos = 0; } } // Insert the proper HTML tag if (header) { s += "</th>"; } else { s += "</td>"; }

  19. } // Return the formatted line return s; } /**     * <p>Initialize the servlet. This is called once when the     * servlet is loaded. It is guaranteed to complete before any     * requests are made to the servlet     *     * @param cfg Servlet configuration information     */

  20. public void init(ServletConfig cfg) throws ServletException { super.init(cfg); } /**    * <p>Destroy the servlet. This is called once when the servlet    * is unloaded.    */ public void destroy() { super.destroy(); }

  21. /**    * <p>Returns information about this servlet    */ public String getServletInfo() { return "Table Filter for Chaining"; } }   接下来的输入流分析就简单得多了。我们只要一行一行地读入表格中的数据,直至找到文件结束标记为止。对每一行,通过查找逗号来取得每一个域,然后将它们格式化成表格的一行。

  22. 8.1.3 触发一个servlet链   在将要链接在一起的servlet组织好之后,你可以通过别名、MIME类型或者HTML请求来触发这个servlet链。每一种方式都其特殊的配置,下面分别看看如何用Java Web服务器和Live Software的JRun来配置这些触发方法。其他服务器的设置也大致相同。  ⑴ servlet别名 servlet别名使你可以设置一个servlet名字或别名来表示一个或多个servlet。servlet链可以用servlet列表表示,该列表中的servlet用逗号分开,并按调用次序的先后排列在一起。

  23.  ① Java Web Server   在配置servlet别名以触发servlet链之前,一定要确认servlet链接功能已经被启动。图4.4显示了站点设置管理屏幕,这里,你可以启用servlet链接功能。  增加一个servlet别名是非常直截了当的事。当服务器接收到对“/Elemetns”的请求,它将调用“javaservlets.samples.Elements”servlet,取得输出后将其传给servlet“javaservlets.samples.TableFilter”作为输入,最后将TableFilter的输出返回给浏览器。如图4.5所示,你只要简单地将servlet名用逗号分隔开来,就可以将任意数量的servlet链接在一起。

  24. 注意,在本书写作时,Java Web Server 1.1还不能完全正确地支持servlet链接。该问题将在后续版本中得到解决。   ② Jrun   在JRun中,servlet链接的配置是通过设置servlet映射来实现的。JRun中servlet别名与servlet是一一对应的,一个servlet只能与惟一的别名对应,所以servlet别名不能支持servlet链接。而servlet映射可以让你将一个名字与一系列servlet或者servlet别名项对应。图4.6显示了如何在JRun中使用servlet映射。

  25. ⑵ servlet别名链接的例子:Elements   为了说明如何使用servlet别名来触发servlet链接,我们先编一个用HTML表格列出元素周期表的servlet。Elements Servlet要实现doGet()来响应HTML GET命令。我们还要设置内容类型然后输出HTML首部信息。Elements Servlet没有格式化输出HTML表格,我们将让它输出表过滤器servlet所需的表格格式信息,并简单地一行一行输出用逗号分隔的数据。

  26. 例2: elements package javaservlets.samples; import javax.servlet.*; import javax.servlet.http.*; /**   * <p>This is a simple servlet that will return a list of   * periodic elements.   */ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, java.io.IOException {

  27. // Create a PrintWriter to write the response java.io.PrintWriter out = new java.io.PrintWriter(resp.getOutputStream()); // Set the content type of the response resp.setContentType("text/html"); // Print the HTML header out.println("<html>"); out.println("<head>");

  28. out.println("<title>Java Servlets Sample - " + "Periodic Elements</title>"); out.println("</head>"); out.println("<h2><center>"); out.println("The Periodic Elements</center></h2>"); out.println("<br>"); // Output special table formatting instructions for // the TableFilter servlet

  29. out.println("<!--table columns=2 header=yes-->"); // Output the table out.println("Symbol,Element"); out.println("Ac,Actinium"); out.println("Ag,Silver"); out.println("Al,Aluminum"); //Etc... out.println("Y,Yttrium");

  30. out.println("Yb,Ytterbium"); out.println("Zn,Zinc"); out.println("Zr,Zirconium"); out.println("<!--end table-->"); // Wrap up out.println("</html>"); out.flush(); out.close(); }

  31. 在你浏览器的URL中输出“/Elements”调用我们在Jrun中配置的servlet映射。在你浏览器的URL中输出“/Elements”调用我们在Jrun中配置的servlet映射。 在刷新时,浏览器向Web服务器发出URL请求,Web服务器找到与这个URL信息对应的servlet映射,然后调用Elemetns Servlet。Elements Servlet处理GET请求并返回未格式化的元素周期表数据给Web服务器。之后,Web服务器发现存在servlet链接,于是将Elements Servlet的输出重定向为servlet链接中下一个servlet,也就是表过滤器的输入。表过滤器重新设置所有HTTP首部,以适应表过滤器的需要,然后读入所有元素周期表数据,表过滤器使用指定的表格格式信息来分析和处理这些数据,最后生成一个格式化的元素周期表。

  32.  ⑶ Mime类型   触发servlet链接的另外一种方法是将一个servlet与特定Mime类型联系起来。当这种Mime类型的应答产生时,输出就会被发送给与之相联系的servlet。由于MIME类型是在servlet向输出流中写入时才确定的,所以用这种方法你可以轻易地将servlet的输出重定向到其他servlet。

  33. ① Java Web Server   如前所述,在所有的工作之前,你必须确认servlet链接功能已经启用(见图4.4)。截止到本书发稿,还没有可以管理MIME类型和servlet映射的图形用户接口(GUI),所以你不得不手工编辑“mimeservlets.properties”文件。这个文件位于目录“/<server_root>/properties/server/javawebserver/webpageservice”。下述代码给出了基本的内容。值得注意的是,MIME类型所映射的servlet名字实际上是该servlet的别名。

  34. # This file maps mime-types to the servlets which process them # This is used by the filter manager to set up chains of servlets # where the ouput of one servlet gets piped to the input of # another servlet based on the mime-type that the servlet specifies # with setContentType("mime-type") # # The default servlet for all mime-types is file.Do not set this # explicitly. #

  35. # Entries in this file should be of the form # mime-type/servletname # ie. # foo/bar=fooServlet # where fooServlet is defined in servlets.properties java-internal/parsed-html=ssi java-internal/template-content=template

  36.  ② Jrun   在JRun中,你可以通过系统管理应用程序设置MIME类型映射。如图4.10所示,你可以把一个servlet和特定的MIME类型联系起来。 MIME类型链接的例子:Indy 500   为了说明如何通过MIME类型来触发servlet链接,让我们编写一个列出Indianapolis 500自1911年起的所有优胜者。就像Elements Servlet一样,我们直接将输入用逗号分隔的各行数据,并用表过滤器将其格式化成HTML表格形式输出。惟一的不同在于我们设置了一个不同的MIME类型,通过这个MIME类型,Web服务器将Indy 500 Servlet的输出重定向为表过滤器servlet的输入(见例3)。

  37. 例3 Indy500.java package javaservlets.samples; import javax.servlet.*; import javax.servlet.http.*; /** <p>This is a simple servlet that will return a list of * past Indianapolis 500 winners    */ public class Indy500 extends HttpServlet { /**

  38. * <p>Performs the HTTP GET operation    * @param req The request from the client    * @param resp The response from the servlet    */ public void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException, java.io.IOException{ // Create a PrintWriter to write the response java.io.PrintWriter out =

  39. new java.io.PrintWriter(resp.getOutputStream()); // Set the content type of the response resp.setContentType("text/table"); // Print the HTML header out.println("<html>"); out.println("<head>"); out.println("<title>Java Servlets Sample - " + "Past Indianapolis 500 Winners</title>"); out.println("</head>"); out.println("<h2><center>");

  40. out.println("Past Indianapolis 500 Winners</center></h2>"); out.println("<br>"); // Output special table formatting instructions for // the TableFilter servlet out.println("<!--table columns=3 header=yes-->"); out.println("Year,Driver,Average Speed"); out.println("1997,Arie Luyendyk,145.827"); out.println("1996,Buddy Lazier,147.956"); out.println("1995,Jacques Villenueve,153.616"); //Etc...

  41. out.println("1912,Joe Dawson,78.719"); out.println("1911,Ray Harroun,74.602"); out.println("<!--end table-->"); // Wrap up out.println("</html>"); out.flush(); out.close(); }

  42. 通过使用JRun中配置的MIME类型映射,调用Indy 500 Servlet的结果将会是格式化了的Indianapolis 500优胜者列表(如图4.12所示)。值得注意的是,我们只要设置servlet的别名就可以了,而无须指定它的全名。   再次重申,Web浏览器向Web服务器发送的是含有servlet名字的HTTP请求,Web服务器调用了servlet(Indy 500),servlet设置了MIME类型“text/table”,而我们已经将这个MIME类型映射到表过滤器servlet。于是,Indy 500所产生的输出将被重定向为表过滤器servlet的输入,表过滤器servlet将数据格式化为HTML表格的形式,并将输出返回给Web服务器。最后Web服务器把这些HTML页发送给浏览器。

  43. ⑷ HTTP请求   触发servlet链接的另一种方法是在HTTP请求中指定servlet链接。不过不是所有的Web服务器都支持这种方法。为了说明HTTP请求中的servlet链接,我们再来编写一个简单的servlet(Solar System),它将返回我们太阳系中所有行星的信息。例4给出了Solar System Servlet的代码。

  44. 例4: SolarSystem.java package javaservlets.samples; import javax.servlet.*; import javax.servlet.http.*; /**    * <p>This is a simple servlet that will return a list of    * the planets in our solar system    */

  45. public class SolarSystem extends HttpServlet{ /**     * <p>Performs the HTTP GET operation     * @param req The request from the client     * @param resp The response from the servlet     */ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, java.io.IOException{ // Set the content type of the response resp.setContentType("text/html"); // Create a PrintWriter to write the response

  46. java.io.PrintWriter out = new java.io.PrintWriter(resp.getOutputStream()); // Print the HTML header out.println("<html>"); out.println("<head>"); out.println("<title>Java Servlets Sample - " + "Planets In Our Solar System</title>"); out.println("</head>"); out.println("<h2><center>"); out.println("Planets In Our Solar System</center></h2>");

  47. out.println("<br>"); // Output special table formatting instructions for // the TableFilter servlet out.println("<!--table columns=5 header=yes-->"); out.println("Planet,Avg. Distance from Sun," + "Time to orbit,Time to spin,Moons"); out.println("Mercury,58 million km,88 days,58.6 days,0"); out.println("Venus,108 million km,225 days,243 days,0"); out.println("Earth,150 million km,365.25 days,24 hours,1");

  48. out.println("Mars,228 million km,687 days,24.62 hours,2"); out.println("Jupiter,778 million km,11.9 years,9.83 hours,16"); out.println("Saturn,1427 million km,29.5 years,10.65 hours,19"); out.println("Uranus,2870 million km,84 years,17.23 hours,15"); out.println("Neptune,4497 million km,164.8 years,16 hours,8"); out.println("Pluto,5913 million km,248 years,6.375 days,1"); out.println("<!--end table-->"); // Wrap up

  49. out.println("</html>"); out.flush(); out.close(); } /** * <p>Initialize the servlet. This is called once when the * servlet is loaded. It is guaranteed to complete before any * requests are made to the servlet * * @param cfg Servlet configuration information */

  50. public void init(ServletConfig cfg) throws ServletException{ super.init(cfg); } /**     * <p>Destroy the servlet. This is called once when the servlet     * is unloaded.     */ public void destroy() super.destroy(); } }

More Related