通过名字查找具体的Action 子类,并将请求委托给这些子类。
这本书对于如何实现一个Action提供了代码示例,但是没有提供任何可供发布的代码。
若需要发布代码,J2EE BluePrints 建议读者参考ApacheStruts。
Apache StrutsApache Struts(http://Jakarta.apache.org/struts)可算是最流行的Servlet 框架。
它与BluePrints 所述的MVC 模式非常接近(在我看来,这两种想法有着同样的思路):Struts 具有高可配置性,而且有相当多的特性(其特性仍在增加),其中包括Front Controller(前端控制器)、动作类及映射、面向XML 的实用类、服务器端JavaBean 的自动填充、带有效性验证的Web 表单以及一些国际化支持。
它还支持一组定制标记以访问服务器端状态、创建HTML、完成表示逻辑以及模板化。
有些开发商已经开始采用并宣传Struts。
Struts 得到了大量的关注,可以认为它是适于大型应用的具有工业强度的框架。
在Struts 中,请求通过一个控制器Servlet 传输。
Action 对象控制请求Servlet 最佳实践49的处理,而且这些动作使用诸如JavaBeans 等组件来完成业务逻辑。
对于有外部配置的Servlet,Struts 在其之上极好地创建了一个完全分派机制,从而消除了URL 和在线行为间的人为联系。
几乎所有请求都通过同一个Servlet进入,客户请求作为请求的一部分,指示了其希望采取的动作(即,登录、加入购物车、结账等),Struts 控制器将把请求分派给一个Action处理。
JSP被用作表示层,尽管也可以使用Apache Velocity 和其他技术。
Struts 是一个开放源代码项目,是在Apache 的开放协作开发模型下开发的。
JavaServer FacesJavaServer Faces(JSF)是Sun 领导的一个Java Community Process(JCP)项目(JSR-127),目前仍处在早期开发阶段。
在写这本书时,它刚刚达到Community Review 的最早阶段,但是已经得到了相当的关注。
JSF 立项文档中原计划定义一个标准Web应用框架,但是目前提交的文档所关注的目标却较为受限,仅仅为请求定义一个包括多个阶段请求处理生命期(即一个表单向导)。
与Struts 很好地集成也是JSF 的一个目标。
Apache TurbineApache Turbine 可能是最古老的Servlet 框架之一,它自1999 年就已经存在了。
此框架拥有处理参数解析和验证、连接池、作业调度、缓存、数据库抽象以及XML-PRC 等服务。
其许多组件都可以独立使用,如对数据库抽象的Torque 工具。
Turbine 将这些组件“捆绑”在一起,从而为构建Web 应用提供了一个可靠的平台,这与J2EE 为企业应用所采用的方式完全一致。
Turbine 与其他框架类似,也基于MVC模型和动作事件抽象。
不过,不同于其他框架,Turbine在视图(View)层提供了额外的支持,而且自称是“Model21”,即优于标准的“Model 2”MVC。
Turbine Views 支持许多模板引擎,不过Apache Velocity 为其首选。
如果篇幅允许,我们还可以讨论更多的框架。
如果你有兴趣学习更多的内容,可以用以下关键字在Google 上查找:TeaServlet、Apache Cocoon、EnhydraBarracuda、JCorporate Expresso 和Japple。
50 第三章使用预编码字符编写Servlet 时你了解到的第一件事就是要用PrintWriter 写字符,而用OutputStream来写字节。
尽管这在形式上是一个很好的建议,但稍有些简化。
需要全面地看待这一事实,因为输出字符并不意味着必须使用一个PrintWriter!PrintWriter有其缺点,具体地说,它必须在内部将char中的各个字符编码为一个byte序列。
如果有已知编码的内容(如,文件、URL 或数据库,甚至是内存中保存的一个String中的内容),那么通常最好采用流。
这样就可以完成一个直接的字节- 字节传输。
除了所保存编码和所需编码之间偶尔会存在字符集不匹配这种少有的情况外,没有必要先将内容解码至一个String,然后再在发送至客户时将其编码为字节。
使用预编码字符则可节省大量开销。
作为演示,例3-1 中的Servlet 使用了一个读取器(reader)来读取一个文本文件,并使用了一个书写器(writer)向客户输出文本。
尽管它遵循了对于文本使用Reader/Writer 类的原则,但是却存在非常浪费而且毫无必要的转换。
例3-1:读入字符,输出字符import java.io.import java.util.prefs.import javax.servlet.import javax.servlet.http.public class WastedConversions extends HttpServlet // 随机文件,仅用于演示String name quotcontent.txtquotpublic void doGetHttpServletRequest req HttpServletResponse resthrows ServletException IOException String file getServletContext.getRealPathnameres.setContentTypequottext/plainquotPrintWriter out res.getWriterreturnFilefile outServlet 最佳实践51public static void returnFileString filename Writer outthrows FileNotFoundException IOException Reader in nulltry in new BufferedReadernew FileReaderfilenamechar buf new char4 1024 // 4K 字符缓冲区int charsReadwhile charsRead in.readbuf -1 out.writebuf 0 charsReadfinally if in null in.close例3-2 中的Servlet 更适于返回一个文本文件。
此Servlet 识别出文件内容是由字节开始的,而且只要其编码与客户所需的编码相匹配,就可以直接作为字节发送。
例3-2:读入字节,输出字节import java.io.import java.util.prefs.import javax.servlet.import javax.servlet.http.public class NoConversions extends HttpServlet String name quotcontent.txtquot // 要发送的演示文件public void doGetHttpServletRequest req HttpServletResponse resthrows ServletException IOException String file getServletContext.getRealPathnameres.setContentTypequottext/plainquotOutputStream out res.getOutputStreamreturnFilefile outpublic static void returnFileString filename OutputStream outthrows FileNotFoundException IOException InputStream in nulltry in new BufferedInputStreamnew FileInputStreamfilename52 第三章byte buf new byte4 1024 // 4K 缓冲区int bytesReadwhile bytesRead in.readbuf -1 out.writebuf 0 bytesReadfinally if in null in.close通过使用预编码字符对于性能有多大的改善呢?这取决于服务器。
对一个2MB文件进行本地访问,以此来测试这两个Servlet,在Tomcat 3.x 下性能有20 的提高;Tomcat 4.x 下则有50 的大幅提高。
尽管这些数字让人印象非常深刻,但它们当然有一个假设,即应用除了传输文本文件之外不做其他工作。
实际的性能提高则取决于Servlet 的业务逻辑。
此技术(如图3-2 所示)对于带宽受限或服务器CPU 受限的应用尤其有用。
字节字节字符浏览器服务器文件字符字节字节图3-2:充分利用预编码字符只要大多数源内容都是预编码的(如,文件、URL,甚至数据库内容),那么“使用预编码字符”这个原则就适用。
例如,使用ResultSet getAsciiStream方法而不是getCharacterStream可以避免对于ASCII 字符串的转换开销,无论在读取数据库还是写至客户时都适用。
还有可能将服务器和数据库之间的带宽减至一半,因为ASCII流的规模大致为UCS-2流的一半。
具体能够得到多大收益,当然还要取决于数据库以及它在内部如何保存和传输数据。
实际上,一些Servlet开发人员用String.getBytes对其静态String内容进行预编码,这样只需对它们进行一次编码。
采用这种极端做法所得到的性能收益是
上一篇:
VC++的路径选择
下一篇:
结合教学实际谈对小学音标教学的心得