﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Java Tools-随笔分类-Servlet</title><link>http://www.blogjava.net/simie/category/23732.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 03 Jul 2007 11:17:14 GMT</lastBuildDate><pubDate>Tue, 03 Jul 2007 11:17:14 GMT</pubDate><ttl>60</ttl><item><title>JSP/Servlet 中的汉字编码问题</title><link>http://www.blogjava.net/simie/archive/2007/07/03/127838.html</link><dc:creator>和田雨</dc:creator><author>和田雨</author><pubDate>Tue, 03 Jul 2007 06:49:00 GMT</pubDate><guid>http://www.blogjava.net/simie/archive/2007/07/03/127838.html</guid><wfw:comment>http://www.blogjava.net/simie/comments/127838.html</wfw:comment><comments>http://www.blogjava.net/simie/archive/2007/07/03/127838.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/simie/comments/commentRss/127838.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/simie/services/trackbacks/127838.html</trackback:ping><description><![CDATA[<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr vAlign=top>
            <td width="100%">
            <h1>JSP/Servlet 中的汉字编码问题</h1>
            <img class=display-img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=1></td>
            <td class=no-print width=192><img height=18 alt=developerWorks src="http://www-128.ibm.com/developerworks/cn/i/dw.gif" width=192></td>
        </tr>
    </tbody>
</table>
<table cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr vAlign=top>
            <td width=10><img height=1 alt="" src="http://www.ibm.com/i/c.gif" width=10></td>
            <td width="100%">
            <table class=no-print cellSpacing=0 cellPadding=0 width=160 align=right border=0>
                <tbody>
                    <tr>
                        <td width=10><img height=1 alt="" src="http://www.ibm.com/i/c.gif" width=10></td>
                        <td>
                        <table cellSpacing=0 cellPadding=0 width=150 border=0>
                            <tbody>
                                <tr>
                                    <td class=v14-header-1-small>文档选项</td>
                                </tr>
                            </tbody>
                        </table>
                        <table class=v14-gray-table-border cellSpacing=0 cellPadding=0 border=0>
                            <tbody>
                                <tr>
                                    <td class=no-padding width=150>
                                    <table cellSpacing=0 cellPadding=0 width=143 border=0>
                                        <img height=1 alt="" src="http://www.ibm.com/i/c.gif" width=8>
                                        <form name=email action=https://www.ibm.com/developerworks/secure/email-it.jsp>
                                            <input type=hidden value="网上就 JSP/Servlet 中 DBCS字符编码问题有许多优秀的文章和讨论，本文对它们作一些整理，并结合IBM WebSphere Application Server3.5（WAS）的解决方法作一些说明，希望它不是多余的。" name=body><input type=hidden value="JSP/Servlet 中的汉字编码问题" name=subject><input type=hidden value=cn name=lang>
                                            <script language=JavaScript type=text/javascript>
                                            <!--
                                            document.write('
                                            <tr valign="top">
                                                <td width="8"><img src="//www.ibm.com/i/c.gif" width="8" height="1" alt=""/></td>
                                                <td width="16"><img src="//www.ibm.com/i/v14/icons/em.gif" height="16" width="16" vspace="3" alt="将此页作为电子邮件发送" /></td>
                                                <td width="122">
                                                <p><a class="smallplainlink" href="javascript:document.email.submit();"><strong>将此页作为电子邮件发送</strong></a></p>
                                                </td>
                                            </tr>
                                            ');
                                            //-->
                                            </script>
                                            <tbody>
                                                <tr vAlign=top>
                                                    <td width=8><img height=1 alt="" src="http://www.ibm.com/i/c.gif" width=8></td>
                                                    <td width=16><img height=16 alt=将此页作为电子邮件发送 src="http://www.ibm.com/i/v14/icons/em.gif" width=16 vspace=3></td>
                                                    <td width=122>
                                                    <p><a class=smallplainlink href="javascript:document.email.submit();"><strong><font color=#5c81a7 size=2>将此页作为电子邮件发送</font></strong></a></p>
                                                    </td>
                                                </tr>
                                                <noscript>
                                                <tr valign="top">
                                                    <td width="8"><img alt="" height="1" width="8" src="//www.ibm.com/i/c.gif"/></td>
                                                    <td width="16"><img alt="" width="16" height="16" src="//www.ibm.com/i/c.gif"/></td>
                                                    <td class="small" width="122">
                                                    <p><span class="ast">未显示需要 JavaScript 的文档选项</span></p>
                                                    </td>
                                                </tr>
                                                </noscript>
                                            </form>
                                        </tbody>
                                    </table>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        <!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- this content will be automatically generated across all content areas --><br><!--end RESERVED FOR FUTURE USE INCLUDE FILES--><br></td>
                    </tr>
                </tbody>
            </table>
            <p>级别: 初级</p>
            <p><a href="http://www-128.ibm.com/developerworks/cn/java/jsp_dbcsz/index.html#author"><u><font color=#996699>IBM</font></u></a>, <br></p>
            <p>2001 年 3 月 01 日</p>
            <blockquote><em>网上就 JSP/Servlet 中 DBCS字符编码问题有许多优秀的文章和讨论，本文对它们作一些整理，并结合IBM WebSphere Application Server3.5（WAS）的解决方法作一些说明，希望它不是多余的。</em> </blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES-->
            <p><a name=N1003B><span class=atitle>问题的起源</span></a></p>
            <p>每个国家（或区域）都规定了计算机信息交换用的字符编码集，如美国的扩展 ASCII码, 中国的 GB2312-80，日本的 JIS 等，作为该国家/区域内信息处理的基础，有着统一编码的重要作用。字符编码集按长度分为 SBCS（单字节字符集），DBCS（双字节字符集）两大类。早期的软件（尤其是操作系统），为了解决本地字符信息的计算机处理，出现了各种本地化版本（L10N），为了区分，引进了 LANG, Codepage 等概念。但是由于各个本地字符集代码范围重叠，相互间信息交换困难；软件各个本地化版本独立维护成本较高。因此有必要将本地化工作中的共性抽取出来，作一致处理，将特别的本地化处理内容降低到最少。这也就是所谓的国际化（I18N）。各种语言信息被进一步规范为 Locale 信息。处理的底层字符集变成了几乎包含了所有字形的 Unicode。</p>
            <p>现在大部分具有国际化特征的软件核心字符处理都是以 Unicode 为基础的，在软件运行时根据当时的 Locale/Lang/Codepage 设置确定相应的本地字符编码设置，并依此处理本地字符。在处理过程中需要实现 Unicode 和本地字符集的相互转换，甚或以 Unicode 为中间的两个不同本地字符集的相互转换。这种方式在网络环境下被进一步延伸，任何网络两端的字符信息也需要根据字符集的设置转换成可接受的内容。</p>
            <p>Java 语言内部是用 Unicode 表示字符的，遵守 Unicode V2.0。Java 程序无论是从/往文件系统以字符流读/写文件，还是往 URL 连接写 HTML 信息，或从 URL 连接读取参数值，都会有字符编码的转换。这样做虽然增加了编程的复杂度，容易引起混淆，但却是符合国际化的思想的。</p>
            <p>从理论上来说，这些根据字符集设置而进行的字符转换不应该产生太多问题。而事实是由于应用程序的实际运行环境不同，Unicode 和各个本地字符集的补充、完善，以及系统或应用程序实现的不规范，转码时出现的问题时时困扰着程序员和用户。 <a name=2></p>
            <br>
            <table cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
                    </tr>
                </tbody>
            </table>
            <table class=no-print cellSpacing=0 cellPadding=0 align=right>
                <tbody>
                    <tr align=right>
                        <td><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
                        <table cellSpacing=0 cellPadding=0 border=0>
                            <tbody>
                                <tr>
                                    <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                                    <td vAlign=top align=right><a class=fbox href="http://www-128.ibm.com/developerworks/cn/java/jsp_dbcsz/index.html#main"><strong><font color=#996699>回页首</font></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br><br>
            <p><a name=N10050><span class=atitle>GB2312-80，GBK，GB18030-2000 汉字字符集及 Encoding</span></a></p>
            <p>其实解决 JAVA 程序中的汉字编码问题的方法往往很简单，但理解其背后的原因，定位问题，还需要了解现有的汉字编码和编码转换。</p>
            <p>GB2312-80 是在国内计算机汉字信息技术发展初始阶段制定的，其中包含了大部分常用的一、二级汉字，和 9 区的符号。该字符集是几乎所有的中文系统和国际化的软件都支持的中文字符集，这也是最基本的中文字符集。其编码范围是高位0xa1－0xfe，低位也是 0xa1-0xfe；汉字从 0xb0a1 开始，结束于 0xf7fe；</p>
            <p>GBK 是 GB2312-80 的扩展，是向上兼容的。它包含了 20902 个汉字，其编码范围是 0x8140-0xfefe，剔除高位 0x80 的字位。其所有字符都可以一对一映射到 Unicode 2.0，也就是说 JAVA 实际上提供了 GBK 字符集的支持。这是现阶段 Windows 和其它一些中文操作系统的缺省字符集，但并不是所有的国际化软件都支持该字符集，感觉是他们并不完全知道 GBK 是怎么回事。值得注意的是它不是国家标准，而只是规范。随着 GB18030-2000国标的发布，它将在不久的将来完成它的历史使命。</p>
            <p>GB18030-2000(GBK2K) 在 GBK 的基础上进一步扩展了汉字，增加了藏、蒙等少数民族的字形。GBK2K 从根本上解决了字位不够，字形不足的问题。它有几个特点，</p>
            <ul>
                <li>它并没有确定所有的字形，只是规定了编码范围，留待以后扩充。
                <li>编码是变长的，其二字节部分与 GBK 兼容；四字节部分是扩充的字形、字位，其编码范围是首字节 0x81-0xfe、二字节0x30-0x39、三字节 0x81-0xfe、四字节0x30-0x39。
                <li>它的推广是分阶段的，首先要求实现的是能够完全映射到 Unicode 3.0 标准的所有字形。
                <li>它是国家标准，是强制性的。 </li>
            </ul>
            <p>现在还没有任何一个操作系统或软件实现了 GBK2K 的支持，这是现阶段和将来汉化的工作内容。</p>
            <p>Unicode 的介绍......就免了吧。</p>
            <p>JAVA 支持的encoding中与中文编程相关的有：(有几个在JDK文档中未列出)</p>
            <table cellSpacing=0 cellPadding=3 border=1>
                <tbody>
                    <tr vAlign=top>
                        <td>ASCII</td>
                        <td>7-bit, 同 ascii7</td>
                    </tr>
                    <tr vAlign=top>
                        <td>ISO8859-1</td>
                        <td>8-bit, 同 8859_1,ISO-8859-1,ISO_8859-1,latin1...</td>
                    </tr>
                    <tr vAlign=top>
                        <td>GB2312-80</td>
                        <td>同gb2312,gb2312-1980,EUC_CN,euccn,1381,Cp1381, 1383, Cp1383, ISO2022CN,ISO2022CN_GB......</td>
                    </tr>
                    <tr vAlign=top>
                        <td>GBK</td>
                        <td>(注意大小写),同MS936</td>
                    </tr>
                    <tr vAlign=top>
                        <td>UTF8</td>
                        <td>UTF-8</td>
                    </tr>
                    <tr vAlign=top>
                        <td>GB18030</td>
                        <td>(现在只有IBM JDK1.3.?有支持), 同Cp1392,1392</td>
                    </tr>
                </tbody>
            </table>
            <p>JAVA 语言采用Unicode处理字符. 但从另一个角度来说，在java程序中也可以采用非Unicode的转码，重要的是保证程序入口和出口的汉字信息不失真。如完全采用ISO-8859-1来处理汉字也能达到正确的结果。网络上流行的许多解决方法，都属于这种类型。为了不致引起混淆，本文不对这种方法作讨论。 </p>
            <br>
            <table cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
                    </tr>
                </tbody>
            </table>
            <table class=no-print cellSpacing=0 cellPadding=0 align=right>
                <tbody>
                    <tr align=right>
                        <td><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
                        <table cellSpacing=0 cellPadding=0 border=0>
                            <tbody>
                                <tr>
                                    <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                                    <td vAlign=top align=right><a class=fbox href="http://www-128.ibm.com/developerworks/cn/java/jsp_dbcsz/index.html#main"><strong><font color=#996699>回页首</font></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br><br>
            <p><a name=3><span class=atitle>中文转码时'?'、乱码的由来</span></a></p>
            <p>两个方向转换都有可能得到错误的结果：</p>
            <ul>
                <li>Unicode--&gt;Byte, 如果目标代码集不存在对应的代码，则得到的结果是0x3f.
                <p>如： <br>"\u00d6\u00ec\u00e9\u0046\u00bb\u00f9".getBytes("GBK") 的结果是 "?&#236;&#233;F?&#249;", Hex 值是3fa8aca8a6463fa8b4. </p>
                <p>仔细看一下上面的结果，你会发现\u00ec被转换为0xa8ac, \u00e9被转换为\xa8a6... 它的实际有效位变长了！这是因为GB2312符号区中的一些符号被映射到一些公共的符号编码，由于这些符号出现在ISO-8859-1或其它一些SBCS字符集中，故它们在Unicode中编码比较靠前，有一些其有效位只有8位，和汉字的编码重叠(其实这种映射只是编码的映射，在显示时仔细不是一样的。Unicode 中的符号是单字节宽，汉字中的符号是双字节宽) . 在Unicode\u00a0--\u00ff 之间这样的符号有20个。了解这个特征非常重要！由此就不难理解为什么JAVA编程中，汉字编码的错误结果中常常会出现一些乱码(其实是符号字符), 而不全是'?'字符, 就比如上面的例子。</p>
                <li>Byte--&gt;Unicode, 如果Byte标识的字符在源代码集不存在，则得到的结果是0xfffd.
                <p>如： <br>Byte ba[] = {(byte)0x81,(byte)0x40,(byte)0xb0,(byte)0xa1}; new String(ba,"gb2312"); </p>
                <p>结果是"?啊", hex 值是"\ufffd\u554a". 0x8140 是GBK字符，按GB2312转换表没有对应的值，取\ufffd. (请注意：在显示该uniCode时，因为没有对应的本地字符，所以也适用上一种情况，显示为一个"?".)</p>
                </li>
            </ul>
            <p>实际编程中，JSP/Servlet 程序得到错误的汉字信息，往往是这两个过程的叠加，有时甚至是两个过程叠加后反复作用的结果. </p>
            <br>
            <table cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
                    </tr>
                </tbody>
            </table>
            <table class=no-print cellSpacing=0 cellPadding=0 align=right>
                <tbody>
                    <tr align=right>
                        <td><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
                        <table cellSpacing=0 cellPadding=0 border=0>
                            <tbody>
                                <tr>
                                    <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                                    <td vAlign=top align=right><a class=fbox href="http://www-128.ibm.com/developerworks/cn/java/jsp_dbcsz/index.html#main"><strong><font color=#996699>回页首</font></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br><br>
            <p><a name=4><span class=atitle>JSP/Servlet 汉字编码问题及在 WAS 中的解决办法</span></a></p>
            <p>
            <p><a name=N100EC><span class=smalltitle><strong><font face=Arial>4.1 常见的 encoding 问题的现象</font></strong></span></a></p>
            <p>网上常出现的 JSP/Servlet encoding 问题一般都表现在 browser 或应用程序端，如: </p>
            <ul>
                <li>浏览器中看到的 Jsp/Servlet 页面中的汉字怎么都成了 &#8217;?&#8217; ?
                <li>浏览器中看到的 Servlet 页面中的汉字怎么都成了乱码？
                <li>JAVA 应用程序界面中的汉字怎么都成了方块？
                <li>Jsp/Servlet 页面无法显示 GBK 汉字。
                <li>JSP 页面中内嵌在&lt;%...%&gt;,&lt;%=...%&gt;等Tag包含的 JAVA code 中的中文成了乱码，但页面的其它汉字是对的。
                <li>Jsp/Servlet 不能接收 form 提交的汉字。
                <li>JSP/Servlet 数据库读写无法获得正确的内容。 </li>
            </ul>
            <p>隐藏在这些问题后面的是各种错误的字符转换和处理（除第3个外，是因为 Java font 设置错误引起的）。解决类似的字符 encoding 问题，需要了解 Jsp/Servlet 的运行过程，检查可能出现问题的各个点。</p>
            <p><a name=N10110><span class=smalltitle><strong><font face=Arial>4.2 JSP/Servlet web 编程时的 encoding 问题</font></strong></span></a></p>
            <p>运行于Java 应用服务器的 JSP/Servlet 为 Browser 提供 HTML 内容，其过程如下图所示：</p>
            <br><br><img height=181 alt="" src="http://www-128.ibm.com/developerworks/cn/java/jsp_dbcsz/image001.gif" width=807> <br>
            <p>其中有字符编码转换的地方有:</p>
            <ul>
                <li>
                <p>JSP 编译。Java 应用服务器将根据 JVM 的 file.encoding 值读取 JSP 源文件，编译生成 JAVA 源文件，再根据 file.encoding 值写回文件系统。如果当前系统语言支持 GBK，那么这时候不会出现 encoding 问题。如果是英文的系统，如 LANG 是 en_US 的 Linux, AIX 或 Solaris，则要将 JVM 的 file.encoding 值置成 GBK 。系统语言如果是 GB2312，则根据需要，确定要不要设置 file.encoding，将 file.encoding 设为 GBK 可以解决潜在的 GBK 字符乱码问题</p>
                <li>
                <p>Java 需要被编译为 .class 才能在 JVM 中执行，这个过程存在与a.同样的 file.encoding 问题。从这里开始 servlet 和 jsp 的运行就类似了，只不过 Servlet 的编译不是自动进行的。对于JSP程序, 对产生的JAVA 中间文件的编译是自动进行的(在程序中直接调用sun.tools.javac.Main类). 因此如果在这一步出现问题的话, 也要检查encoding和OS的语言环境，或者将内嵌在JSP JAVA Code 中的静态汉字转为 Unicode, 要么静态文本输出不要放在 JAVA code 中。对于Servlet, javac 编译时手工指定-encoding 参数就可以了。</p>
                <li>
                <p>Servlet 需要将 HTML 页面内容转换为 browser 可接受的 encoding 内容发送出去。依赖于各 JAVA App Server 的实现方式，有的将查询 Browser 的 accept-charset 和 accept-language 参数或以其它猜的方式确定 encoding 值，有的则不管。因此采用固定encoding 也许是最好的解决方法。对于中文网页，可在 JSP 或 Servlet 中设置 contentType="text/html; charset=GB2312"；如果页面中有GBK字符，则设置为contentType="text/html; charset=GBK"，由于IE 和 Netscape对GBK的支持程度不一样，作这种设置时需要测试一下。因为16位 JAVA char在网络传送时高8位会被丢弃，也为了确保Servlet页面中的汉字（包括内嵌的和servlet运行过程中得到的）是期望的内码，可以用 PrintWriter out=res.getWriter() 取代 ServletOutputStream out=res.getOutputStream(). PrinterWriter 将根据contentType中指定的charset作转换 (ContentType需在此之前指定！); 也可以用OutputStreamWriter封装 ServletOutputStream 类并用write(String)输出汉字字符串。对于 JSP，JAVA Application Server 应当能够确保在这个阶段将嵌入的汉字正确传送出去。</p>
                <li>
                <p>这是解释 URL 字符 encoding 问题。如果通过 get/post 方式从 browser 返回的参数值中包含汉字信息， servlet 将无法得到正确的值。SUN的 J2SDK 中，HttpUtils.parseName 在解析参数时根本没有考虑 browser 的语言设置，而是将得到的值按 byte 方式解析。这是网上讨论得最多的 encoding 问题。因为这是设计缺陷，只能以 bin 方式重新解析得到的字符串；或者以 hack HttpUtils 类的方式解决。参考文章 2 均有介绍，不过最好将其中的中文 encoding GB2312、 CP1381 都改为 GBK，否则遇到 GBK 汉字时，还是会有问题。 Servlet API 2.3 提供一个新的函数 HttpServeletRequest.setCharacterEncoding 用于在调用 request.getParameter(&#8220;param_name&#8221;) 前指定应用程序希望的 encoding，这将有助于彻底解决这个问题。</p>
                </li>
            </ul>
            <p><a name=N10145><span class=smalltitle><strong><font face=Arial>4.3 IBM Websphere Application Server 中的解决方法</font></strong></span></a></p>
            <p>WebSphere Application Server 对标准的 Servlet API 2.x 作了扩展，提供较好的多语言支持。运行在中文的操作系统中，可以不作任何设置就可以很好地处理汉字。下面的说明只是对WAS是运行在英文的系统中，或者需要有GBK支持时有效。</p>
            <p>上述c,d情况，WAS 都要查询 Browser 的语言设置，在缺省状况下， zh, zh-cn 等均被映射为 JAVA encoding CP1381（注意： CP1381 只是等同于 GB2312 的一个 codepage，没有 GBK 支持）。这样做我想是因为无法确认 Browser 运行的操作系统是支持GB2312, 还是 GBK，所以取其小。但是实际的应用系统还是要求页面中出现 GBK 汉字，最著名的是朱总理名字中的&#8220;?F"(rong2 ，0xe946，\u9555)，所以有时还是需要将 Encoding/Charset 指定为 GBK。当然 WAS 中变更缺省的 encoding 没有上面说的那么麻烦，针对 a,b，参考文章 5，在 Application Server 的命令行参数中指定 -Dfile.encoding=GBK 即可； 针对 d，在 Application Server 的命令行参数中指定-Ddefault.client.encoding=GBK。如果指定了-Ddefault.client.encoding=GBK，那么c情况下可以不再指定charset。</p>
            <p>上面列出的问题中还有一个关于Tag&lt;%...%&gt;,&lt;%=...%&gt;中的 JAVA 代码里包含的静态文本未能正确显示的问题，在WAS中的解决方法是除了设置正确的file.encoding, 还需要以相同方法设置-Duser.language=zh -Duser.region=CN。这与JAVA locale的设置有关。</p>
            <p><a name=N10154><span class=smalltitle><strong><font face=Arial>4.4 数据库读写时的 encoding 问题</font></strong></span></a></p>
            <p>JSP/Servlet 编程中经常出现 encoding 问题的另一个地方是读写数据库中的数据。</p>
            <p>流行的关系数据库系统都支持数据库 encoding，也就是说在创建数据库时可以指定它自己的字符集设置，数据库的数据以指定的编码形式存储。当应用程序访问数据时，在入口和出口处都会有 encoding 转换。对于中文数据，数据库字符编码的设置应当保证数据的完整性. GB2312，GBK，UTF-8 等都是可选的数据库 encoding；也可以选择 ISO8859-1 (8-bit)，那么应用程序在写数据之前须将 16Bit 的一个汉字或 Unicode 拆分成两个 8-bit 的字符，读数据之后则需将两个字节合并起来，同时还要判别其中的 SBCS 字符。没有充分利用数据库 encoding 的作用，反而增加了编程的复杂度，ISO8859-1不是推荐的数据库 encoding。JSP/Servlet编程时，可以先用数据库管理系统提供的管理功能检查其中的中文数据是否正确。</p>
            <p>然后应当注意的是读出来的数据的 encoding，JAVA 程序中一般得到的是 Unicode。写数据时则相反。</p>
            <p><a name=N10163><span class=smalltitle><strong><font face=Arial>4.5 定位问题时常用的技巧</font></strong></span></a></p>
            <p>定位中文encoding问题通常采用最笨的也是最有效的办法――在你认为有嫌疑的程序处理后打印字符串的内码。通过打印字符串的内码，你可以发现什么时候中文字符被转换成Unicode，什么时候Unicode被转回中文内码，什么时候一个中文字成了两个 Unicode 字符，什么时候中文字符串被转成了一串问号，什么时候中文字符串的高位被截掉了&#8230;&#8230;</p>
            <p>取用合适的样本字符串也有助于区分问题的类型。如：&#8221;aa啊aa?@aa&#8221; 等中英相间、GB、GBK特征字符均有的字符串。一般来说，英文字符无论怎么转换或处理，都不会失真（如果遇到了，可以尝试着增加连续的英文字母长度）。</p>
            <br>
            <table cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td><img height=1 alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%"><br><img height=6 alt="" src="http://www.ibm.com/i/c.gif" width=8 border=0></td>
                    </tr>
                </tbody>
            </table>
            <table class=no-print cellSpacing=0 cellPadding=0 align=right>
                <tbody>
                    <tr align=right>
                        <td><img height=4 alt="" src="http://www.ibm.com/i/c.gif" width="100%"><br>
                        <table cellSpacing=0 cellPadding=0 border=0>
                            <tbody>
                                <tr>
                                    <td vAlign=center><img height=16 alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width=16 border=0><br></td>
                                    <td vAlign=top align=right><a class=fbox href="http://www-128.ibm.com/developerworks/cn/java/jsp_dbcsz/index.html#main"><strong><font color=#996699>回页首</font></strong></a></td>
                                </tr>
                            </tbody>
                        </table>
                        </td>
                    </tr>
                </tbody>
            </table>
            <br><br>
            <p><a name=N1016F><span class=atitle>结束语</span></a></p>
            <p>其实 JSP/Servlet 的中文encoding 并没有想像的那么复杂，虽然定位和解决问题没有定规，各种运行环境也各不尽然，但后面的原理是一样的。了解字符集的知识是解决字符问题的基础。不过，随着中文字符集的变化，不仅仅是 java 编程，中文信息处理中的问题还是会存在一段时间的。 </p>
            <br><br>
            <p><a name=resources><span class=atitle>参考资料 </span></a></p>
            <ul>
                <li><a href="http://www.ibm.com/developerworks/cn/java/java_chinese/index.html"><u><font color=#5c81a7>Java 编程技术中汉字问题的分析及解决</font></u></a> <br><br>
                <li><a href="http://oss.software.ibm.com/cvs/icu/~checkout~/icu/source/tools/makeconv/gb18030/gb18030.html"><u><font color=#5c81a7>GB18030</font></u></a> <br><br>
                <li><a href="http://www.ibm.com/software/webservers/appserv/doc/v35/ae/infocenter/was/040209.html"><u><font color=#5c81a7>Setting language encoding in web applications: Websphere applications Server</font></u></a> <br></li>
            </ul>
            <br><br>
            <p><a name=author><span class=atitle>关于作者</span></a></p>
            <table cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td colSpan=3><img height=5 alt="" src="http://www.ibm.com/i/c.gif" width="100%"></td>
                    </tr>
                    <tr vAlign=top align=left>
                        <td>
                        <p>&#160;</p>
                        </td>
                        <td><img height=5 alt="" src="http://www.ibm.com/i/c.gif" width=4></td>
                        <td width="100%">
                        <p>IBM has authored this article</p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/simie/aggbug/127838.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/simie/" target="_blank">和田雨</a> 2007-07-03 14:49 <a href="http://www.blogjava.net/simie/archive/2007/07/03/127838.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSP/Servlet的重定向技术综述</title><link>http://www.blogjava.net/simie/archive/2007/07/02/127536.html</link><dc:creator>和田雨</dc:creator><author>和田雨</author><pubDate>Mon, 02 Jul 2007 05:38:00 GMT</pubDate><guid>http://www.blogjava.net/simie/archive/2007/07/02/127536.html</guid><wfw:comment>http://www.blogjava.net/simie/comments/127536.html</wfw:comment><comments>http://www.blogjava.net/simie/archive/2007/07/02/127536.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/simie/comments/commentRss/127536.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/simie/services/trackbacks/127536.html</trackback:ping><description><![CDATA[　　<strong>1.RequestDispatcher.forward()</strong><br><br>　　是在服务器端起作用,当使用forward()时,Servlet engine传递HTTP请求从当前的Servlet or JSP到另外一个Servlet,JSP 或普通HTML文件,也即你的form提交至a.jsp,在a.jsp用到了forward()重定向至b.jsp,此时form提交的所有信息在b.jsp都可以获得,参数自动传递.<br><br>　　但forward()无法重定向至有frame的jsp文件,可以重定向至有frame的html文件,同时forward()无法在后面带参数传递,比如servlet?name=frank,这样不行,可以程序内通过response.setAttribute("name",name)来传至下一个页面.<br><br>　　重定向后浏览器地址栏URL不变.<br><br>　　例:在servlet中进行重定向<br><br>　　public void doPost(HttpServletRequest request,HttpServletResponse response)<br><br>　　throws ServletException,IOException<br><br>　　{<br><br>　　response.setContentType("text/html; charset=gb2312");<br><br>　　ServletContext sc = getServletContext();<br><br>　　RequestDispatcher rd = null;<br><br>　　rd = sc.getRequestDispatcher("/index.jsp");　　 //定向的页面<br><br>　　rd.forward(request, response);<br><br>　　}<br><br>　　通常在servlet中使用，不在jsp中使用。<br><br>　　<strong>2.response.sendRedirect()</strong><br><br>　　是在用户的浏览器端工作,sendRedirect()可以带参数传递,比如servlet?name=frank传至下个页面,同时它可以重定向至不同的主机上,sendRedirect()可以重定向有frame.的jsp文件.<br><br>　　重定向后在浏览器地址栏上会出现重定向页面的URL<br><br>　　例:在servlet中重定向<br><br>　　public void doPost(HttpServletRequest request,HttpServletResponse response)<br><br>　　throws ServletException,IOException<br><br>　　{<br><br>　　response.setContentType("text/html; charset=gb2312");<br><br>　　response.sendRedirect("/index.jsp");<br><br>　　}<br><br>　　由于response是jsp页面中的隐含对象，故在jsp页面中可以用response.sendRedirect()直接实现重定位。<br><br>　　注意：<br><br>　　(1).使用response.sendRedirect时，前面不能有HTML输出。<br><br>　　这并不是绝对的，不能有HTML输出其实是指不能有HTML被送到了浏览器。事实上现在的server都有cache机制，一般在8K（我是说JSP　SERVER），这就意味着，除非你关闭了cache，或者你使用了out.flush()强制刷新，那么在使用sendRedirect之前，有少量的HTML输出也是允许的。<br><br>　　(2).response.sendRedirect之后，应该紧跟一句return;<br><br>　　我们已经知道response.sendRedirect是通过浏览器来做转向的，所以只有在页面处理完成后，才会有实际的动作。既然你已经要做转向了，那么后的输出还有什么意义呢？而且有可能会因为后面的输出导致转向失败。<br><br>　　比较：<br><br>　　(1).Request Dispatcher.forward()是容器中控制权的转向，在客户端浏览器地址栏中不会显示出转向后的地址；<br><br>　　(2).response.sendRedirect()则是完全的跳转，浏览器将会得到跳转的地址，并重新发送请求链接。这样，从浏览器的地址栏中可以看到跳转后的链接地址。<br><br>　　前者更加高效，在前者可以满足需要时，尽量使用RequestDispatcher.forward()方法.<br><br>　　注：在有些情况下，比如，需要跳转到一个其它服务器上的资源，则必须使用HttpServletResponse.sendRequest()方法。<br><br>　　<strong>3.&lt;jsp:forward page="" /&gt;</strong><br><br>　　它的底层部分是由RequestDispatcher来实现的，因此它带有RequestDispatcher.forward()方法的印记。<br><br>　　如果在&lt;jsp:forward&gt;之前有很多输出,前面的输出已使缓冲区满,将自动输出到客户端,那么该语句将不起作用,这一点应该特别注意。<br><br>　　另外要注意：它不能改变浏览器地址，刷新的话会导致重复提交<br><br>　　<strong>4.修改HTTP header的Location属性来重定向</strong><br><br>　　通过设置直接修改地址栏来实现页面的重定向。<br>jsp文件代码如下：<br><br>　　＜%<br><br>　　response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);<br><br>　　String newLocn = "/newpath/jsa.jsp";<br><br>　　response.setHeader("Location",newLocn);<br><br>　　%＞<br><br>　　<strong>5.JSP中实现在某页面停留若干秒后,自动重定向到另一页面</strong><br><br>　　在html文件中，下面的代码：<br><br>　　&lt;meta http-equiv="refresh" content="300; url=target.jsp"&gt;<br><br>　　它的含义：在5分钟之后正在浏览的页面将会自动变为target.html这一页。代码中300为刷新的延迟时间，以秒为单位。targer.html为你想转向的目标页,若为本页则为自动刷新本页。<br><br>　　由上可知，可以通过setHeader来实现某页面停留若干秒后,自动重定向到另一页面。<br><br>　　关键代码：<br><br>　　String content=stayTime+";URL="+URL;<br><br>　　response.setHeader("REFRESH",content);<br><br>　　如果总结得不够全面，请各位发表自己的意见或经验。
<img src ="http://www.blogjava.net/simie/aggbug/127536.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/simie/" target="_blank">和田雨</a> 2007-07-02 13:38 <a href="http://www.blogjava.net/simie/archive/2007/07/02/127536.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Servlet实现动态图文结合输出</title><link>http://www.blogjava.net/simie/archive/2007/07/02/127535.html</link><dc:creator>和田雨</dc:creator><author>和田雨</author><pubDate>Mon, 02 Jul 2007 05:34:00 GMT</pubDate><guid>http://www.blogjava.net/simie/archive/2007/07/02/127535.html</guid><wfw:comment>http://www.blogjava.net/simie/comments/127535.html</wfw:comment><comments>http://www.blogjava.net/simie/archive/2007/07/02/127535.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/simie/comments/commentRss/127535.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/simie/services/trackbacks/127535.html</trackback:ping><description><![CDATA[<a href="http://www.stcore.com/java/2006-11-17/1163704120d113828.html">http://www.stcore.com/java/2006-11-17/1163704120d113828.html</a>
<img src ="http://www.blogjava.net/simie/aggbug/127535.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/simie/" target="_blank">和田雨</a> 2007-07-02 13:34 <a href="http://www.blogjava.net/simie/archive/2007/07/02/127535.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>监听器统计在线的人数</title><link>http://www.blogjava.net/simie/archive/2007/07/02/127533.html</link><dc:creator>和田雨</dc:creator><author>和田雨</author><pubDate>Mon, 02 Jul 2007 05:33:00 GMT</pubDate><guid>http://www.blogjava.net/simie/archive/2007/07/02/127533.html</guid><wfw:comment>http://www.blogjava.net/simie/comments/127533.html</wfw:comment><comments>http://www.blogjava.net/simie/archive/2007/07/02/127533.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/simie/comments/commentRss/127533.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/simie/services/trackbacks/127533.html</trackback:ping><description><![CDATA[由于工作需要,最近在找一些解决方案,发现Listener是一个很好的东西, 能够监听到session,application的create,destroy,可以监听到session,application<br><br>&nbsp;属性绑定的变化,考虑了一下,可以应用在"在线人数统计","数据缓存"等各个方面,<br><br>下面是整理的一些资料.<br><br><br><br>Listener是Servlet的监听器，它可以监听客户端的请求、服务端的操作等。通过监听器，可以自动激发一些操作，比如监听在线的用户的数量。当增加一个HttpSession时，就激发sessionCreated(HttpSessionEvent se)方法，这样就可以给在线人数加1。常用的监听接口有以下几个：<br><br>ServletContextAttributeListener监听对ServletContext属性的操作，比如增加、删除、修改属性。<br><br>ServletContextListener监听ServletContext。当创建ServletContext时，激发contextInitialized(ServletContextEvent sce)方法；当销毁ServletContext时，激发contextDestroyed(ServletContextEvent sce)方法。<br><br>HttpSessionListener监听HttpSession的操作。当创建一个Session时，激发session Created(HttpSessionEvent se)方法；当销毁一个Session时，激发sessionDestroyed (HttpSessionEvent se)方法。<br><br>HttpSessionAttributeListener监听HttpSession中的属性的操作。当在Session增加一个属性时，激发attributeAdded(HttpSessionBindingEvent se) 方法；当在Session删除一个属性时，激发attributeRemoved(HttpSessionBindingEvent se)方法；当在Session属性被重新设置时，激发attributeReplaced(HttpSessionBindingEvent se) 方法。 <br><br>下面我们开发一个具体的例子，这个监听器能够统计在线的人数。在ServletContext初始化和销毁时，在服务器控制台打印对应的信息。当ServletContext里的属性增加、改变、删除时，在服务器控制台打印对应的信息。 <br><br>要获得以上的功能，监听器必须实现以下3个接口：<br><br>HttpSessionListener<br><br>ServletContextListener<br><br>ServletContextAttributeListener <br><br>我们看具体的代码，见示例14-9。 <br><br>【程序源代码】 <br><br>1&nbsp;// ==================== Program Discription =====================<br><br>2&nbsp;// 程序名称：示例14-9 : EncodingFilter .java<br><br>3&nbsp;// 程序目的：学习使用监听器<br><br>4&nbsp;// ==============================================================<br><br>5&nbsp;import javax.servlet.http.*;<br><br>6&nbsp;import javax.servlet.*;<br><br>7<br><br>8&nbsp;public class OnLineCountListener implements HttpSessionListener,<br><br>ServletContextListener,ServletContextAttributeListener<br><br>9&nbsp;{<br><br>10&nbsp;&nbsp;private int count;<br><br>11&nbsp;&nbsp;private ServletContext context = null;<br><br>12&nbsp;&nbsp;<br><br>13&nbsp;&nbsp;public OnLineCountListener()<br><br>14&nbsp;&nbsp;{<br><br>15&nbsp;&nbsp;&nbsp;count=0;<br><br>16&nbsp;&nbsp;&nbsp;//setContext();<br><br>17&nbsp;&nbsp;}<br><br>18&nbsp;&nbsp;//创建一个session时激发<br><br>19&nbsp;&nbsp;public void sessionCreated(HttpSessionEvent se) <br><br>20&nbsp;&nbsp;{<br><br>21&nbsp;&nbsp;&nbsp;count++;<br><br>22&nbsp;&nbsp;&nbsp;setContext(se);<br><br>23&nbsp;&nbsp;&nbsp;<br><br>24&nbsp;&nbsp;}<br><br>25&nbsp;&nbsp;//当一个session失效时激发<br><br>26&nbsp;&nbsp;public void sessionDestroyed(HttpSessionEvent se) <br><br>27&nbsp;&nbsp;{<br><br>28&nbsp;&nbsp;&nbsp;count--;<br><br>29&nbsp;&nbsp;&nbsp;setContext(se);<br><br>30&nbsp;&nbsp;}<br><br>31&nbsp;&nbsp;//设置context的属性，它将激发attributeReplaced或attributeAdded方法<br><br>32&nbsp;&nbsp;public void setContext(HttpSessionEvent se)<br><br>33&nbsp;&nbsp;{<br><br>34&nbsp;&nbsp;&nbsp;se.getSession().getServletContext().<br>
<img src ="http://www.blogjava.net/simie/aggbug/127533.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/simie/" target="_blank">和田雨</a> 2007-07-02 13:33 <a href="http://www.blogjava.net/simie/archive/2007/07/02/127533.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Servlets和JSP开发原则（转载）</title><link>http://www.blogjava.net/simie/archive/2007/07/02/127513.html</link><dc:creator>和田雨</dc:creator><author>和田雨</author><pubDate>Mon, 02 Jul 2007 04:51:00 GMT</pubDate><guid>http://www.blogjava.net/simie/archive/2007/07/02/127513.html</guid><wfw:comment>http://www.blogjava.net/simie/comments/127513.html</wfw:comment><comments>http://www.blogjava.net/simie/archive/2007/07/02/127513.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/simie/comments/commentRss/127513.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/simie/services/trackbacks/127513.html</trackback:ping><description><![CDATA[<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>和<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>技术是用<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>开发服务器端应用的主要技术，是开发商务应用表示端的标准。<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>开发者喜欢使用它有多种原因，其一是对于已经熟悉<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>语言的开发者来说这个技术容易学习；其二是<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>把&#8220;一次编写，到处运行&#8221;的理念带入到Web应用中，实现了&#8220;一次编写，到处实现&#8221;。而且更为重要的是，如果遵循一些良好的设计原则的话，就可以把表示和内容相分离，创造出高质量的、可以复用的、易于维护和修改的应用程序。比方说，在HTML文档中如果嵌入过多的<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>代码（scriptlet），就会导致开发出来的应用非常复杂、难以阅读、不容易复用，而且对以后的维护和修改也会造成困难。事实上，在CSDN的<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>/<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a><a class=channel_keylink href="http://bbs.bc-cn.net/"><u><font color=#0000ff>论坛</font></u></a>中，经常可以看到一些提问，代码很长，可以逻辑却不是很清晰，大量的HTML和<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>代码混杂在一起，让人看得一头雾水。这就是随意开发的弊端。<br><br>　　如果你已经基本了解<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>和<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>的各项技术（最好也开发过一些Web应用），那么我们可以一起探讨一下如何开发&#8220;好&#8221;的应用的一些指导原则。我们首先对<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>和<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>技术做一个浏览。<br><br>　<span style="FONT-WEIGHT: bold">　</span><a class=channel_keylink style="FONT-WEIGHT: bold" href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a><span style="FONT-WEIGHT: bold">和</span><a class=channel_keylink style="FONT-WEIGHT: bold" href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a><span style="FONT-WEIGHT: bold">概览</span><br><br>　　早期的动态网页主要采用CGI（Common Gateway Interface，公共网关<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%BD%D3%BF%DA"><u><font color=#0000ff>接口</font></u></a>）技术，你可以使用不同的语言编写CGI程序，如<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/vb/Index.html"><u><font color=#0000ff>VB</font></u></a>、C/<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/cjj/Index.html"><u><font color=#0000ff>C++</font></u></a>或<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/delphi/Index.html"><u><font color=#0000ff>Delphi</font></u></a>等。虽然CGI技术发展成熟且功能强大，但由于编程困难、效率低下、修改复杂等缺点，所以有逐渐被取代的趋势。在所有的新技术中，<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>/<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>具备更高效、更容易编程、功能更强、更安全和具有良好的可移植性，因而被许多人认为是未来最有发展前途的动态网站技术。<br><br>　　与CGI相似，<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>支持请求/响应模型。当一个客户向服务器递交一个请求时，服务器把请求送给<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>，<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>负责处理请求并生成响应，然后送给服务器，再由服务器发送给客户。与CGI不同的是，<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>没有生成新的进程，而是与HTTP Server处于同一进程中。它通过使用线程技术，减小了服务器的开销。<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>处理请求的过程是这样的：当收到来自客户端的请求后，调用service方法，该方法中<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>先判断到来的请求是什么类型的（GET/POST/HEAD&#8230;），然后调用相应的处理方法（doGet/doPost/doHead&#8230;）并生成响应。<br><br>　　别看这么复杂，其实简单说来<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>就是一个<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>类。与一般类的不同之处是，这个类运行在一个<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>容器内，可以提供<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=session&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>session</font></u></a>管理和对象生命周期管理。因而当你使用<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>的时候，你可以得到<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>平台的所有好处，包括安全性管理、使用JDBC访问<a class=channel_keylink href="http://www.bc-cn.net/Article/sjk/Index.html"><u><font color=#0000ff>数据库</font></u></a>以及跨平台的能力。而且，<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>使用线程，因而可以开发出效率更高的Web应用。<br><br>　　<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>Server Pages (<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>)<br><br>　　<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>技术是J2EE的一个关键技术，它在更高一级的层次上抽象<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>。它可以让常规静态HTML与动态产生的内容相结合，看起来像一个HTML网页，却作为<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>来运行。现在有许多商业应用服务器支持<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>技术，比如BEA WebLogic、IBM WebSphere、 JRun等等。使用<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>比用<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>更简单。如果你有一个支持<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>的Web服务器，并且有一个<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>文件，你可以把它放倒任何静态HTML文件可以放置的位置，不用编译，不用打包，也不用进行ClassPath的设置，就可以像访问普通网页那样访问它，服务器会自动帮你做好其他的工作。<br><br>　　<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>工作原理<br><br>　　<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a> 文件看起来就像一个普通静态HTML文件，只不过里面包含了一些<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>代码。它使用.jsp的后缀，用来告诉服务器这个文件需要特殊的处理。当我们访问一个<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>页面的时候，这个文件首先会被<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>引擎翻译为一个<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>源文件，其实就是一个<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>，并进行编译，然后像其他<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>一样，由<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>引擎来处理。<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>引擎装载这个类，处理来自客户的请求，并把结果返回给客户，如下图所示： <br><br><img onerror="this.src='/Article/UploadFDL02/200602/20060217130122992.jpg';" hspace=3 src="http://www.360doc.com/DownloadImg/15540/389120_1.jpg" align=middle vspace=1 border=1><br>图1： 调用<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>页面的流程<br><br>　　以后再有客户访问这个页面的时候，只要该文件没有发生过更改，<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>引擎就直接调用已经装载的<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>。如果已经做过修改的话，那就会再次执行以上过程，翻译、编译并装载。其实这就是所谓的&#8220;第一人惩罚&#8221;。因为首次访问的时候要执行一系列以上的过程，所以会耗费一些时间；以后的访问就不会这样了。 <br><strong><br>开发原则</strong><br><br>　　这一部分我们列出一些开发原则，重点是<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>页面。关于如何分离表现和内容的MVC因为要涉及到<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>和<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>的整合，我们稍候再谈。 <br><br>　　不要在<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>页面中嵌入过量的<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>代码：对于非常简单或是测试性的代码，把所有的<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a> 代码直接放入<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>页面内是没有问题的。但是这种方法不应该被过度使用，否则就会产生一大堆HTML和<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>混合起来的代码，让人难以阅读和理解。解决方法是写一个单独的类，用来执行相关的计算。一旦这个类测试通过，就可以把它放在任何执行同样计算的场合中。这样可以促进代码的复用。 <br><br>　　选择合适的包含（include）机制: 如果一个应用中每个页面有一样的抬头和底部，或者还有导航条，那么就应该把它们放到一个单独的文件中，然后在每一个页面中使用包含机制把它们加入到这个页面中：<br><br>Include 指令： ＜%@ include file="filename" %＞或等效xml语法<br>＜jsp:directive.includefile=&#8221;filename&#8221; /＞ <br><br>Include 动作： ＜jsp:include page="page.jsp" flush="true" /＞ <br><br>　　Include指令是当<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>页面翻译为<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>的时候包含另外一个文件，Include 动作是当请求时包含另外一个文件的输出。如果被包含的文件不是经常改动的时候，我建议使用Include 指令，这样速度更快。如果被包含的文件需要不时改动或者知道请求时才能决定需要包含的内容时，那么应该使用Include 动作。<br><br>　　如果你使用<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>标准标记库（<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>Server pages Standard Tag Library即JSTL）的话，那么还有第三中包含机制＜c:import＞，可以用来包含本地或者远程的资源。例如： <br><br>＜c:import url="./copyright.html"/＞<br>＜c:import url="http://www.somewhere.com/hello.xml"/＞<br><br>　　不要把业务逻辑和表示混合在一起： 复杂的应用涉及大量的代码，因而把业务逻辑和前端的表示相分离就显得格外重要，这种分离可以让任何一方的变化不会影响到另外一方。所以，所有的<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>代码都应该限制在表示层，可是如果这样的话，你如何实现你的业务逻辑呢？这就是<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>Bean所做的事情。<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>Bean技术是一个独立于平台的组件模型，它让开发者编写、测试通过一个组件后，可以随处使用，提高了复用性。在<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>技术中，<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>Bean实现了业务逻辑部分，它把数据返回给<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>页面，由<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>页面负责格式化数据并输出到客户端的浏览器。在<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>页面中使用<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>Bean组件的好处是： <br><br>　　产生了可以复用的组件：任何应用都可以使用这些组件 <br><br>　　可以把业务逻辑和表示相分离：你可以修改数据的显示方式而不用考虑业务逻辑。这样做的结果也可以明确工作中开发人员的分工，网页开发人员可以把精力放到如何显示数据上，<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>开发者则更为关注业务逻辑的实现。 <br><br>　　对于<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>Bean你不用提供源代码，这样你的代码就不会被浏览器网页的人轻易获得，可以保护你的劳动成果。 <br><br>　　如果你的应用中使用了EJB组件，那么业务逻辑就应该放置在EJB中，因为EJB模型提供了生命周期管理、事务管理以及多客户访问域对象（Entity Beans）。你可以仔细看一下Enterprise BluePrints中的例子，它就是这么做的。 <br><br>　　使用定制的标记： 上面我们已经讨论过，把所有<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>代码嵌入到<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>页面内并不合适，因为网页开发人员并不一定懂得<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>语言，更难以理解<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>语法。<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>Bean可以封装很多<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>代码，不过在<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>页面内使用<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>Bean仍然要求页面开发人员了解一些<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>语法。<br><br>　　<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>技术中包含了定制标记库的功能。<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>开发人员可以生成自己的标记库，这样网页设计人员就可以使用类似HTML的语法来使用这些标记。编写和使用自己定制的标记库可以在更大程度上促进业务逻辑和表示的分离。使用定制标记库主要有以下好处： <br><br>　　<strong>可以消除在<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>页面中使用scriptlet</strong>　标记使用的任何参数都可以通过<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%CA%F4%D0%D4"><u><font color=#0000ff>属性</font></u></a>传入，从而不需要使用<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>代码就可以达到希望的目的。 <br><br>　　<strong>可以简化使用</strong>　网页设计人员不需要学会使用<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>语法，他们可以用类似HTML语法就可以使用标记。 <br>不懂<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>的网页设计人员可以使用标记库来完成单独使用HTML不能完成的任务。 <br><br>　　<strong>提高了复用性</strong>　标记库完全可以复用，这可以节省开发和测试的时间。Scriptlet代码只能在&#8220;拷贝粘贴&#8221;级别上进行&#8220;复用&#8221;。 <br><br>　　简单说来，你可以像用HTML构建表示层一样使用标记库完成非常复杂的任务。下面是表页标记库的一些注意事项： <br><br>　　1. 保持简洁性：如果一个标记需要好几个<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%CA%F4%D0%D4"><u><font color=#0000ff>属性</font></u></a>的话，那么尽可能把它分为几个标记。 <br><br>　　2. 保持复用性：同标记的使用人员（网页设计人员）多多交流，尽量开发出可以高度复用的标记库。 <br><br>　　3. 不要一切都从头开始：现在已经有一些可以免费使用的标记库，比如Jakarta Taglibs。如果你要用到一个标记，先看看是不是已经有现成的可以使用。 <br><br>　　不要&#8220;重新发明轮子&#8221;，不要一切从头开始： 通过定制组件可以提高复用性，不过定制组件仍然需要编写、测试和调试程序。问题是这个事情别人可能已经实现了，而且你的实现方式并不一定比人家做得更好。这就是<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>标准标记库（<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>Server Pages Standard Tag Library, JSTL）要做的事情（JSTL请参考JSTL官方网站）。JSTL提供了循环、读<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%CA%F4%D0%D4"><u><font color=#0000ff>属性</font></u></a>、遍历各种<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/sjjg/Index.html"><u><font color=#0000ff>数据结构</font></u></a>、条件表达式求值等各种标记。它也提供了一些复杂的标记，甚至像解析<a class=channel_keylink href="http://www.bc-cn.net/Article/web/xml/Index.html"><u><font color=#0000ff>XML</font></u></a>文档的标记它都有。所以如果你要用到一个标记的话，最好先看看有没有别人已经实现的可以使用，而不要次次从头开始，自己搞一套。 <br><br>　　使用JSTL表达使语言（JSTL Expression Language）： 传递给<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>页面的数据一般通过<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>作用域<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%CA%F4%D0%D4"><u><font color=#0000ff>属性</font></u></a>或者请求参数来进行。专门为网页开发者设计的表达式语言（Expression Language, EL）把使用作用域<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%CA%F4%D0%D4"><u><font color=#0000ff>属性</font></u></a>传递信息作为从业务逻辑向<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>页面传递信息的标准方式。这里要注意的是，EL只是<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>技术中关键的一个方面，并不是一种通用的程序设计语言。相反，它只是一种数据访问语言，它可以简化应用程序的数据的访问，不用Scriptlet和请求时表达式求值就可以访问数据。<br><br>　　在<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>中，网页设计师要使用表达式语法＜%= name %＞或<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>Bean组件来取得某些变量或<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%CA%F4%D0%D4"><u><font color=#0000ff>属性</font></u></a>的值，例如： <br><br>＜tagLib:tag attribute="＜%=<br><br>pageContext.getAttribute("name") %＞"＞<br><br>　　或 <br><br>＜%= aCustomerBean.getAddress().getCountry() %＞<br><br>　　表达使语言让网页设计师可以使用简化的语法来访问信息。如果你只是要访问一个简单的变量，你可以使用这样的语法：<br><br>＜tagLib:tag attribute="${name}"＞<br><br>　　如果你要访问一个嵌套<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>Bean的<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%CA%F4%D0%D4"><u><font color=#0000ff>属性</font></u></a>，你可以这样：<br><br>＜tagLib:tag attribute ="${<br><br>aCustomerBean.address.country}"＞<br><br>　　表达式语言（EL）借用了<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>Script 的语法，所以如果你对<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>Script 很熟悉的话，你就会觉得巨爽。<br><br>　　使用过滤器（filter）： 过滤器是一个对象，可以传输请求或修改响应。它可以在请求到达<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>/<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>之前对其进行预处理，而且能够在响应离开<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>/<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>之后对其进行后处理。所以如果你有几个<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>/<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>需要执行同样的数据转换或页面处理的话，你就可以写一个过滤器类，然后在部署描述文件（web.xml）中把该过滤器与对应的<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>/<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>联系起来。<br><br>　　创建过滤器其实很容易，你只须实现javax.servlet.Filter<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%BD%D3%BF%DA"><u><font color=#0000ff>接口</font></u></a>及它的三个方法：<br><br>public void init(FilterConfig config)<br><br>public void doFilter(<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>Request req, <a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>Response rep, <br><br>FilterChain chain)<br><br>public void destroy()<br><br>　　这样，你就可以完成你的过滤器。<br><br>使用可移植的安全模型：大部分的应用服务器都提供了安全模型，不过一般它们都是针对某一个服务器或某一个厂商专有的。如果你的应用需要移植的话，那么你的应用最好使用可以移植的安全模型。如果你的应用有一些预先定义的固定用户的话，那么你可以使用FROM验证和BASIC验证。可是如果你要动态生成客户的话（一般都是这种情况），你可能就需要使用服务器特定的API来创建和管理用户。这样当你的应用移植到另外一个服务器时，你可能就会碰到API不兼容的问题。这种情况下，最好的解决方法是使用适配器（Adapter）模式（如果你对设计模式不熟悉的话，请参看GoF的《设计模式》一书）。 <br><br>　　用<a class=channel_keylink href="http://www.bc-cn.net/Article/sjk/Index.html"><u><font color=#0000ff>数据库</font></u></a>来保存持久性数据： <a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>/<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>中可以使用HttpSession对象也就是会话对象来保存用户的临时数据。不过如果你想保存持久性数据的时候，你应该使用<a class=channel_keylink href="http://www.bc-cn.net/Article/sjk/Index.html"><u><font color=#0000ff>数据库</font></u></a>，数据保存数据会更安全，而且对客户所用的浏览器没有什么要求。这样即使你的应用服务器由于某种原因崩溃了，你的数据依然良好。 <br><br>　　高速缓存页面： 应用程序中总有一些东西是相对固定的，而另外一些东西是经常变化的。你应该使用静态的HTML文档来存储那些相对固定的内容，这样客户端就可以进行高速缓存，客户每次访问你的应用时，只需访问已经改动的部分。这样可以加快客户的访问速度。 <br><br>　　使用连接池： 如果你要自己写<a class=channel_keylink href="http://www.bc-cn.net/Article/sjk/Index.html"><u><font color=#0000ff>数据库</font></u></a>访问代码的话，我觉得使用你应该学会如何使用<a class=channel_keylink href="http://www.bc-cn.net/Article/sjk/Index.html"><u><font color=#0000ff>数据库</font></u></a>连接池技术。每一个服务器都有针对<a class=channel_keylink href="http://www.bc-cn.net/Article/sjk/Index.html"><u><font color=#0000ff>数据库</font></u></a>连接池的配置文档，你要学习一下如何使用。<a class=channel_keylink href="http://www.bc-cn.net/Article/sjk/Index.html"><u><font color=#0000ff>数据库</font></u></a>连接池可以加速你的应用的数据访问的速度，而且由于服务器替你管理了<a class=channel_keylink href="http://www.bc-cn.net/Article/sjk/Index.html"><u><font color=#0000ff>数据库</font></u></a>连接，这可以节省你的很多工作。 <br><br>　　缓存<a class=channel_keylink href="http://www.bc-cn.net/Article/sjk/Index.html"><u><font color=#0000ff>数据库</font></u></a>的访问结果： 如果你的应用要对<a class=channel_keylink href="http://www.bc-cn.net/Article/sjk/Index.html"><u><font color=#0000ff>数据库</font></u></a>进行频繁访问的话，你可以使用一个对象来缓存你的数据，这样你就可以节省大量访问<a class=channel_keylink href="http://www.bc-cn.net/Article/sjk/Index.html"><u><font color=#0000ff>数据库</font></u></a>的开销。在《J2EE核心模式》和《实用J2EE设计模式编程指南》两本书中都有关于值对象模式（Value Object Pattern）的详细探讨，你可以参考这两本书来获得相应的知识。 <br><br>　　使用数据访问对象模式：如果你的应用需要访问多个<a class=channel_keylink href="http://www.bc-cn.net/Article/sjk/Index.html"><u><font color=#0000ff>数据库</font></u></a>系统或者可能会移植到其它的存储系统中，那么你针对特定厂商的优化代码就可能会失效。使用通用的代码存在执行效率的问题，而使用优化代码又存在移植的问题。所以就产生了数据访问对象模式（Data Access Object Pattern, DAO），该模式既提供了各<a class=channel_keylink href="http://www.bc-cn.net/Article/sjk/Index.html"><u><font color=#0000ff>数据库</font></u></a>厂商的适应性，又能利用到他们提供的独特的好处。按照<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=%C3%E6%CF%F2%B6%D4%CF%F3"><u><font color=#0000ff>面向对象</font></u></a>的分离任务的原则，该模式将与企业信息系统（Enterprise Information System, EIS）通讯需要的逻辑隔离到它自己的类中。这样，事物对象，如<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>/<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>组件、<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>Bean就可以利用数据访问对象（DAO）处理所有与EIS有关的事务。 <br><br>　　最好采用<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>的<a class=channel_keylink href="http://www.bc-cn.net/Article/web/xml/Index.html"><u><font color=#0000ff>XML</font></u></a>语法： <a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>技术中经常存在着两种完成同一个任务的语法，一种是常规的<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>语法，一种是对应的<a class=channel_keylink href="http://www.bc-cn.net/Article/web/xml/Index.html"><u><font color=#0000ff>XML</font></u></a>语法。虽然两种语法作用相同，你最好还是使用<a class=channel_keylink href="http://www.bc-cn.net/Article/web/xml/Index.html"><u><font color=#0000ff>XML</font></u></a>语法。存在两种语法的原因是，<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>语法可以与以前的代码兼容，而J2EE使用<a class=channel_keylink href="http://www.bc-cn.net/Article/web/xml/Index.html"><u><font color=#0000ff>XML</font></u></a>作为其交换数据的核心，所以同时提供了<a class=channel_keylink href="http://www.bc-cn.net/Article/web/xml/Index.html"><u><font color=#0000ff>XML</font></u></a>语法。随着J2EE的发展，<a class=channel_keylink href="http://www.bc-cn.net/Article/web/xml/Index.html"><u><font color=#0000ff>XML</font></u></a>的作用会越来越大，所以我建议你使用<a class=channel_keylink href="http://www.bc-cn.net/Article/web/xml/Index.html"><u><font color=#0000ff>XML</font></u></a>语法。 <br><br>　　研究Sun提供的J2EE BluePrints: Sun的Enterprise BluePrints 提供了大量指导原则、设计模式和很好的例子（宠物店，Pet Store）。你可以好好研究一下这些内容，这样可以提高你的设计和开发水平。 <br><br>　　<strong>整合<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>和<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a></strong><br><br>　　<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>技术规范种给出了两种使用<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>开发Web应用的方式，这两种方式可以归纳为模型一和模型二，这两种模型的主要差别在于它们处理业务的流程不同。模型一，如下图所示，称之为<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>+<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>Beans模型。在这一模型中，<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>页面独自响应请求并将处理结果返回给客户，所有的数据通过<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>Bean来处理，<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>实现页面的表现。<br><br><img onerror="this.src='/Article/UploadFDL02/200602/20060217130123372.jpg';" hspace=3 src="http://www.360doc.com/DownloadImg/15540/389120_2.jpg" align=middle vspace=1 border=1><br>图2： <a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>模型一 <br><br>　　从上图可以看出，模型一也实现了页面表现和业务逻辑相分离。然而使用这种方式就要在<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>页面使用大量的<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>代码，当需要处理的业务逻辑很复杂时，这种情况会变得非常糟糕。大量嵌入式代码使整个页面程序变得异常复杂。对于前端界面设计的网页开发人员来说，这简直是一场噩梦。所以，模型一不能满足大型应用的需要，但是对于小型应用，因为该模型简单，不用涉及诸多要素，从而可以很好地满足小型应用的需要，所以在简单应用中，可以考虑模型一。<br><br>　　模型二，如下图所示，称之为<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>+<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>+<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>Beans模型。这一模型结合了<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>和<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>技术，充分利用了<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>和<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>两种技术原有的优势。这个模型使用<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>技术来表现页面，使用<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>技术完成大量的事务处理，使用Bean来存储数据。<a class=channel_keylink href="http://www.bc-cn.net/Article/Search.asp?Field=Title&amp;ClassID=&amp;keyword=Servlet&amp;Submit=+%CB%D1%CB%F7+"><u><font color=#0000ff>Servlet</font></u></a>用来处理请求的事务，充当一个控制者的角色，并负责向客户发送请求。它创建<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>需要的Bean和对象，然后根据用户请求的行为，决定将哪个<a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>页面发送给客户。<br><br><img onerror="this.src='/Article/UploadFDL02/200602/20060217130123452.jpg';" hspace=3 src="http://www.360doc.com/DownloadImg/15540/389120_3.jpg" align=middle vspace=1 border=1><br>图3： <a class=channel_keylink href="http://www.bc-cn.net/Article/web/jsp/Index.html"><u><font color=#0000ff>JSP</font></u></a>模型二<br><br>　　从开发的观点看，模型二具有更清晰的页面表现，清楚的开发角色的划分，可以充分利用开发团队中的网页设计人员和<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>开发人员。这些优势在大型项目中表现得尤为突出，网页设计人员可以充分发挥自己的美术和设计才能来充分表现页面，程序编写人员可以充分发挥自己的业务逻辑处理思维，实现项目中的业务处理。<br><br>　　另外，从设计结构来看，这种模型充分体现了模型视图控制器（MVC）的设计架构。事实上，现存的很多开发框架都是基于这种模型的，充分实现了MVC ，例如Apache Struts框架和<a class=channel_keylink href="http://www.bc-cn.net/Article/kfyy/java/Index.html"><u><font color=#0000ff>Java</font></u></a>Server Faces框架 <br>
<img src ="http://www.blogjava.net/simie/aggbug/127513.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/simie/" target="_blank">和田雨</a> 2007-07-02 12:51 <a href="http://www.blogjava.net/simie/archive/2007/07/02/127513.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用Java Servlets 2.4实现过滤</title><link>http://www.blogjava.net/simie/archive/2007/07/02/127503.html</link><dc:creator>和田雨</dc:creator><author>和田雨</author><pubDate>Mon, 02 Jul 2007 04:28:00 GMT</pubDate><guid>http://www.blogjava.net/simie/archive/2007/07/02/127503.html</guid><wfw:comment>http://www.blogjava.net/simie/comments/127503.html</wfw:comment><comments>http://www.blogjava.net/simie/archive/2007/07/02/127503.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/simie/comments/commentRss/127503.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/simie/services/trackbacks/127503.html</trackback:ping><description><![CDATA[Servlet API 很久以前就已成为企业应用开发的基石，而 Servlet 过滤器则是对 J2EE 家族的相对较新的补充。本文将向您介绍 Servlet 过滤器体系结构，定义过滤器的许多应用，并指导您完成典型过滤器实现的三个步骤。同时本文还会透露bean 的一些激动人心的变化，预计刚发布的 Java Servlet 2.4规范会引入这些变化。
<p>　　Servlet 过滤器是可插入的 Web 组件，它允许我们实现 Web 应用程序中的预处理和后期处理逻辑。过滤器支持 servlet 和 JSP 页面的基本请求处理功能，比如日志记录、性能、安全、会话处理、XSLT 转换，等等。 过滤器最初是随 Java Servlet 2.3 规范发布的，最近定稿的 2.4 规范对它进行了重大升级。在此我将向您介绍 Servlet 过滤器的基础知识 ―― 比如总体的体系结构设计、实现细节，以及在 J2EE Web 应用程序中的典型应用，还会涉及一些预计最新的 Servlet 规范将会提供的扩展功能。 </p>
<p>　　<strong>Servlet 过滤器是什么？</strong><br><br>　　Servlet 过滤器是小型的 Web 组件，它们拦截请求和响应，以便查看、提取或以某种方式操作正在客户机和服务器之间交换的数据。过滤器是通常封装了一些功能的 Web 组件，这些功能虽然很重要，但是对于处理客户机请求或发送响应来说不是决定性的。典型的例子包括记录关于请求和响应的数据、处理安全协议、管理会话属性，等等。过滤器提供一种面向对象的模块化机制，用以将公共任务封装到可插入的组件中，这些组件通过一个配置文件来声明，并动态地处理。</p>
<p>　　Servlet 过滤器中结合了许多元素，从而使得过滤器成为独特、强大和模块化的 Web 组件。也就是说，Servlet 过滤器是：</p>
<ul>
    <li><strong>声明式的</strong>：过滤器通过 Web 部署描述符（web.xml）中的 XML 标签来声明。这样允许添加和删除过滤器，而无需改动任何应用程序代码或 JSP 页面。 <br>
    <li><strong>动态的</strong>：过滤器在运行时由 Servlet 容器调用来拦截和处理请求和响应。 <br>
    <li><strong>灵活的</strong>：过滤器在 Web 处理环境中的应用很广泛，涵盖诸如日志记录和安全等许多最公共的辅助任务。过滤器还是灵活的，因为它们可用于对来自客户机的直接调用执行预处理和后期处理，以及处理在防火墙之后的 Web 组件之间调度的请求。最后，可以将过滤器链接起来以提供必需的功能。 <br>
    <li><strong>模块化的</strong>：通过把应用程序处理逻辑封装到单个类文件中，过滤器从而定义了可容易地从请求/响应链中添加或删除的模块化单元。 <br>
    <li><strong>可移植的</strong>：与 Java 平台的其他许多方面一样，Servlet 过滤器是跨平台和跨容器可移植的，从而进一步支持了 Servler 过滤器的模块化和可重用本质。 <br>
    <li><strong>可重用的</strong>：归功于过滤器实现类的模块化设计，以及声明式的过滤器配置方式，过滤器可以容易地跨越不同的项目和应用程序使用。 <br>
    <li><strong>透明的</strong>：在请求/响应链中包括过滤器，这种设计是为了补充（而不是以任何方式替代）servlet 或 JSP 页面提供的核心处理。因而，过滤器可以根据需要添加或删除，而不会破坏 servlet 或 JSP 页面。 </li>
</ul>
<p>　　所以 Servlet 过滤器是通过一个配置文件来灵活声明的模块化可重用组件。过滤器动态地处理传入的请求和传出的响应，并且无需修改应用程序代码就可以透明地添加或删除它们。最后，过滤器独立于任何平台或者 Servlet 容器，从而允许将它们容易地部署到任何相容的 J2EE 环境中。</p>
<p>　　在接下来的几小节中，我们将进一步考察 Servlet 过滤器机制的总体设计，以及实现、配置和部署过滤器所涉及的步骤。我们还将探讨 Servlet 过滤器的一些实际应用，最后简要考察一下模型-视图-控制器（MVC）体系结构中包含的 Servlet 过滤器，从而结束本文的讨论。</p>
<p>　　<strong>Servlet 过滤器体系结构<br></strong><br>　　正如其名称所暗示的， Servlet 过滤器用于拦截传入的请求和/或传出的响应，并监视、修改或以某种方式处理正在通过的数据流。过滤器是自包含、模块化的组件，可以将它们添加到请求/响应链中，或者在无需影响应用程序中其他 Web 组件的情况下删除它们。过滤器仅只是改动请求和响应的运行时处理，因而不应该将它们直接嵌入 Web 应用程序框架，除非是通过 Servlet API 中良好定义的标准接口来实现。 </p>
<p>　　Web 资源可以配置为没有过滤器与之关联（这是默认情况）、与单个过滤器关联（这是典型情况），甚至是与一个过滤器链相关联。那么过滤器究竟做什么呢？ 像 servlet 一样，它接受请求并响应对象。然后过滤器会检查请求对象，并决定将该请求转发给链中的下一个组件，或者中止该请求并直接向客户机发回一个响应。如果请求被转发了，它将被传递给链中的下一个资源（另一个过滤器、servlet 或 JSP 页面）。在这个请求设法通过过滤器链并被服务器处理之后，一个响应将以相反的顺序通过该链发送回去。这样就给每个过滤器都提供了根据需要处理响应对象的机会。</p>
<p>　　当过滤器在 Servlet 2.3 规范中首次引入时，它们只能过滤 Web 客户机和客户机所访问的指定 Web 资源之间的内容。如果该资源然后将请求调度给其他 Web 资源，那就不能向幕后委托的任何请求应用过滤器。2.4 规范消除了这个限制。Servlet 过滤器现在可以应用于 J2EE Web 环境中存在请求和响应对象的任何地方。因此，Servlet 过滤器可以应用在客户机和 servlet 之间、servlet 和 servlet 或 JSP 页面之间，以及所包括的每个 JSP 页面之间。这才是我所称的强大能力和灵活性！</p>
<img src ="http://www.blogjava.net/simie/aggbug/127503.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/simie/" target="_blank">和田雨</a> 2007-07-02 12:28 <a href="http://www.blogjava.net/simie/archive/2007/07/02/127503.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>servlet2.5/jsp2.1的新特征</title><link>http://www.blogjava.net/simie/archive/2007/07/02/127500.html</link><dc:creator>和田雨</dc:creator><author>和田雨</author><pubDate>Mon, 02 Jul 2007 04:20:00 GMT</pubDate><guid>http://www.blogjava.net/simie/archive/2007/07/02/127500.html</guid><wfw:comment>http://www.blogjava.net/simie/comments/127500.html</wfw:comment><comments>http://www.blogjava.net/simie/archive/2007/07/02/127500.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/simie/comments/commentRss/127500.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/simie/services/trackbacks/127500.html</trackback:ping><description><![CDATA[<div>2005年9月26日，Sun公司和JSR154的专家组发布Servlet&nbsp;API的一个新的版本。在一般情况下，一个JSR的新版本仅仅包括对以前少数有名无实的规范进行去除更新。但这次，新版本中增加新的特征和变化，他们对Servlets的产生重要影响，使得Servlet的版本升到了 2.5。<br>在这篇文章里，我主要谈谈Servlet2.5版本中的新特征。描述每一个变化，阐述那些必要变化产生的背景，并展示如何在基于Servlet的项目中利用这些变化。　<br>事实上，这是我为JavaWorld提供的第六篇关于Servlet&nbsp;API更新资料的文章。这篇文章意在两个目的：从眼前来看，向你介绍 Servlet的新特征。从长远来看，是展现Servlet变化的历史概要，这样当你基于老的Servlet&nbsp;API版本进行编码的时候，你可以正确地决定哪些特征和功能你可以使用，而哪些特征和功能你不应该使用。你可以参考我先前写的关于Servlet的文章。<br>注意：当你想实践这些Servlet的新特征和功能时，你要知道的是：并不是所有的Servlet容器和Java企业级应用服务器都能立即适用于最新版的Servlet&nbsp;API，写这篇文章时（2006年1月2日），Jetty&nbsp;6&nbsp;server和Sun公司的GlassFish&nbsp;server是公认最好的支持Servlet2.5的容器，而Apache&nbsp;Tomcat5.5和Jboss&nbsp;4.0目前只支持Servlet2.4。<br>Servlet2.5一些变化的介绍：<br>1）&nbsp;&nbsp;&nbsp;&nbsp;基于最新的J2SE&nbsp;5.0开发的。<br>2）&nbsp;&nbsp;&nbsp;&nbsp;支持注释。<br>3）&nbsp;&nbsp;&nbsp;&nbsp;web.xml中的几处配置更加方便。<br>4）&nbsp;&nbsp;&nbsp;&nbsp;去除了少数的限制。<br>5）&nbsp;&nbsp;&nbsp;&nbsp;优化了一些实例<br><strong>J2SE&nbsp;5.0的产物：</strong><br>从一开始，Servlet&nbsp;2.5&nbsp;规范就列出J2SE&nbsp;5.0&nbsp;(JDK&nbsp;1.5)&nbsp;作为它最小的平台要求。它使得Servlet2.5只能适用基于J2SE&nbsp;5.0开发的平台，这个变动意味着所有J2SE5.0的新特性可以保证对Servlet2.5程序员有用。<br>传统意义上，Servlet和JEE版本一直与JDK的版本保持同步发展，但是这次，Servlet的版本跳过1.4版本。专家组认为版本的加速增长是正当的，因为J2SE5.0提出一个引人注目的，Servlet和JEE规范都要利用的特征??注释。<br><strong>注释：</strong><br>注释是作为JSR175的一部分提出的（一种为Java语言设计提供便利的Metadata）一种新的语言特色。它是利用Metadata为Java 编码结构（类，方法，域等等）装饰的一种机制。它不能像代码那样执行，但是可以用于标记代码，这个过程是基于Metadata信息的代码处理机，通过更新他们的事件行为来实现的。<br><br>我们可以凭借不同的技巧来注释类和方法，例如连续地标记接口或者是@deprecated&nbsp;Javadoc评论。这种新式的Metadata可以便利地提供了一种标准的机制来实现注释功能，以及通过库来创建用户自己的注释类型的变量。<br>下面是一个简单的Web&nbsp;service&nbsp;注释例子：<br>import&nbsp;javax.jws.WebService;<br>import&nbsp;javax.jws.WebMethod;<br>@WebService<br>public&nbsp;class&nbsp;HelloWorldService&nbsp;{<br>&nbsp;&nbsp;@WebMethod<br>&nbsp;&nbsp;public&nbsp;String&nbsp;helloWorld()&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;"Hello&nbsp;World!";<br>&nbsp;&nbsp;}<br>}<br>@WebService和@WebMethod这两个注释类型，在JSR181（为Java平台提供的Web&nbsp;ServicesMetadata）有详细说明，可以像类一样的引用，标记这个类作为一个Web&nbsp;service并且标记它的helloWorld（）方法做为一个Web&nbsp;service方法。对于他们本身来说，注释只是写在那里并没有什么作用，好像在岗位上做记录一样，但是，一个容器一旦加载这个类并对那些注释进行二进制编码，就可以把这个类连到Web&nbsp;service上。<br>注释可以接受属性/值这些参数。它保存着参数的信息并且可以利用这些参数来更改被请求的事件行为。例如下面更高级的注释例子：<br>@WebService(<br>&nbsp;name&nbsp;=&nbsp;"PingService",<br>&nbsp;&nbsp;targetNamespace=http://acme.com/ping<br>)<br>@SOAPBinding(<br>&nbsp;&nbsp;style=SOAPBinding.Style.RPC,<br>&nbsp;&nbsp;use=SOAPBinding.Use.LITERAL<br>)<br>public&nbsp;class&nbsp;Ping&nbsp;{<br>&nbsp;&nbsp;@WebMethod(operationName&nbsp;=&nbsp;"Foo")<br>&nbsp;&nbsp;public&nbsp;void&nbsp;foo()&nbsp;{&nbsp;}<br>}<br>一旦加载了这个类，一个正确配置的容器就会识别出注释及其参数，并将这个做为一个PingService通过利用remote-procedure- call/literal的编码方式与一个Foo&nbsp;operation相连。实际上，注释便指明了类和类的容器之间的联系。<br><br>Java本身的规范（JSR175）仅仅有少量的注释类型变量。而这些有趣的注释类型变量主要来自于其他的JSRs：<br>"JSR&nbsp;250:&nbsp;Java平台的公共注释<br>"JSR&nbsp;220:&nbsp;企业级JavaBeans&nbsp;3.0&nbsp;<br>"JSR&nbsp;224:&nbsp;基于XML的Java&nbsp;API&nbsp;Web&nbsp;Services&nbsp;(JAX-WS)&nbsp;2.0&nbsp;<br>"JSR&nbsp;181:&nbsp;Java平台的Web&nbsp;Services&nbsp;Metadata&nbsp;<br>Servlet2.5中的注释：<br>回到Servlet2.5上来，一种新的规范描述了几种注释在Servlet环境中是如何工作的。功能弱的Servlet容器忽略了这些规范，然而JEE容器中的Servlet却严格遵守这些规范。<br><br>有的注释提供了在XML注册的可选择性，否则就要注册在配置文件web.xml中。有的作为容器的请求来执行其任务，否则就由Servlet亲自来执行。还有的注释两者都具备。<br><br>注释准确的定义不是完全固定的，因为Servlet本身并没有定义注释。它仅仅解释了它们如何影响Servlet环境，下面是注释的一个简要的概述，你可以看到在JEE5中它们的用途：<br><br>"@Resource&nbsp;and&nbsp;@Resources：@Resource位于类或变量中以对Servlet容器进行&#8220;资源注入&#8221;。当容器识别出这个注释时，它会在获得服务地位之前，用适当的值实现带注释的变量的重新注入。通过使用这种注释，你不必利用JNDI来查找命令和在配置文件web.xml中手动声明资源。服务器通过Servlet的自我调整来执行它的任务。变量的名称和类型由映像机制自动确定，尽管你可以利用注释的参数来超越这一限制。一个注入的资源可以是数据源，Java信息服务目的文件或者是环境设置的标量。下面是一个例子：<br>@Resource&nbsp;javax.sql.DataSource&nbsp;catalog;<br>public&nbsp;getData()&nbsp;{<br>&nbsp;&nbsp;Connection&nbsp;con&nbsp;=&nbsp;catalog.getConnection();<br>}<br>现在，在这段Servlet代码变成服务之前，容器会定位JNDI变量，并对于目录变量进行手动分配。<br>为了效率，仅仅某些类支持资源注入，这些类有：Servlets，Servlet过滤器，Servlet事件监听器，JSP标签操作器，JSP库事件监听器，用于处理beans的JSF，以及一些与Serlvets无关的类。<br>"@Resources注释与@Resource相似，但是它用于一组@Resource注释。它们都来自JSR250，是Java平台的公共注释。<br>"@PostConstruct&nbsp;and&nbsp;@PreDestroy：可以使方法成为带有生命周期的方法。@PostConstruct方法用于资源注入初始化之后。@PreDestroy方法用于Servlet脱离服务并释放注入的资源的时候。回收的方法必须是事实的方法，返回void并且不可以抛出任何异常。这些注释本质上使得任何方法都成为init()和destroy()的子方法，这些特征也来自与JSR250。<br>"@EJB：类似于@Resource，设计用于注入企业级的JavaBeans。比起@Resource，它略有不同，在于@EJB的参数特定设计用来定位EJB的参数。这个注释来自EJB3.0的规范。<br>"@WebServiceRef：与@Resource&nbsp;和&nbsp;@EJB相似，设计用于注入Web&nbsp;service参数。来自于JAX-WS2.0规范。<br>"@PersistenceContext,&nbsp;@PersistenceContexts,&nbsp;@PersistenceUnit,&nbsp;and&nbsp;@PersistenceUnits：这些注释来自EJB3.0规范来支持Java对象的持久化。<br>"@DeclareRoles:&nbsp;定义应用程序中安全角色的使用。当定义一个Servlet类时，在配置文件web.xml中&lt;security-role&gt;标签中对它进行设置，来自JSR250。<br>"&nbsp;@RunAs：用于声明哪个类应该执行。当定义一个Servlet类时，在配置文件web.xml中&lt;run-as&gt;标签中对它进行设置。来自于JSR250。
<p>注释的执行：<br>不论你使用注释与否??尤其在你不使用时??它对于理解服务器上程序的执行有着重要意义。为了让服务器识别类中的注释，它必须加载这些类，这就意味着服务器必须是启动着的，服务器通过WEB-INF/classes目录下和WEB－INF/lib目录下的所有类文件来查找注释。（每个规范下，服务器不必查找这两个目录以外的目录。）你可以通过下面的方法指明&lt;web-app&gt;根的属性而不必使用如何进行注释：<br>&lt;web-app&nbsp;xmlns="http://java.sun.com/xml/ns/javaee"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;version="2.5"&nbsp;full="true"&gt;<br>&lt;/web-app&gt;<br>web.xml的便利：<br>Servlet2.5对于web.xml引入几个小的变动，使得它更加方便。<br>Servlet名称的通配符化：<br>首先，当你写&lt;filter-mapping&gt;,你现在可以在&lt;Servlet-name&gt;标签中使用*号来代表所有的Servlets。而以前，你必须一次把一个Servlet绑定到过滤器上，像这样：<br><br>&lt;filter-mapping&gt;<br>&nbsp;&nbsp;&lt;filter-name&gt;Image&nbsp;Filter&lt;/filter-name&gt;<br>&nbsp;&nbsp;&lt;Servlet-name&gt;ImageServlet&lt;/Servlet-name&gt;<br>&lt;/filter-mapping&gt;&nbsp;<br><br>现在，你可以一次绑定所有的Servlets：<br><br>&lt;filter-mapping&gt;<br>&nbsp;&nbsp;&lt;filter-name&gt;Image&nbsp;Filter&lt;/filter-name&gt;<br>&nbsp;&nbsp;&lt;Servlet-name&gt;*&lt;/Servlet-name&gt;&nbsp;&nbsp;&lt;!?新特征&nbsp;--&gt;<br>&lt;/filter-mapping&gt;<br><br>这有着很大用途，例如：<br><br>&lt;filter-mapping&gt;<br>&nbsp;&nbsp;&lt;filter-name&gt;Dispatch&nbsp;Filter&lt;/filter-name&gt;<br>&nbsp;&nbsp;&lt;Servlet-name&gt;*&lt;/Servlet-name&gt;<br>&nbsp;&nbsp;&lt;dispatcher&gt;FORWARD&lt;/dispatcher&gt;<br>&lt;/filter-mapping&gt;<br><br>映射的复合模式：<br>其次，当我们写&lt;Servlet-mapping&gt;&nbsp;或者&nbsp;&lt;filter-mapping&gt;时，你现在可以在同一的标签中采用复合匹配的标准。以前一个&lt;Servlet-mapping&gt;只支持一个&lt;url-pattern&gt;元素，现在它不只支持一个，例如：<br>&lt;Servlet-mapping&gt;<br>&nbsp;&nbsp;&lt;Servlet-name&gt;color&lt;/Servlet-name&gt;<br>&nbsp;&nbsp;&lt;url-pattern&gt;/color/*&lt;/url-pattern&gt;<br>&nbsp;&nbsp;&lt;url-pattern&gt;/colour/*&lt;/url-pattern&gt;<br>&lt;/Servlet-mapping&gt;<br><br>同样地，以前&lt;filter-mapping&gt;也是只支持一个&lt;url-pattern&gt;&nbsp;或者一个&nbsp;&lt;Servlet-name&gt;。现在它对于每个元素都可以支持任意多个：<br><br>&lt;filter-mapping&gt;<br>&nbsp;&nbsp;&lt;filter-name&gt;Multipe&nbsp;Mappings&nbsp;Filter&lt;/filter-name&gt;<br>&nbsp;&nbsp;&lt;url-pattern&gt;/foo/*&lt;/url-pattern&gt;<br>&nbsp;&nbsp;&lt;Servlet-name&gt;Servlet1&lt;/Servlet-name&gt;<br>&nbsp;&nbsp;&lt;Servlet-name&gt;Servlet2&lt;/Servlet-name&gt;<br>&nbsp;&nbsp;&lt;url-pattern&gt;/bar/*&lt;/url-pattern&gt;<br>&lt;/filter-mapping&gt;<br><br>HTTP方法名：<br><br>最近，你可以将合法的HTTP/1.1方法名放进&lt;http-method&gt;元素中。当你使用这些方法时，&lt;http- method&gt;将指明&lt;security-constraint&gt;标记里的方法应该被应用。从以前来看，它仅限于HTTP/1.1的7 个标准方法：GET，POST，PUT，DELETE，HEAD，OPTIONS和TRACE。但是，HTTP/1.1允许对方法进行扩展，WebDAV 是用于这种扩展的普遍技术。在Servlet2.5中，你可以安全地约束任何可能的HTTP方法名，标准及扩展，包括WebDAV方法，例如：LOCK， UNLOCK，COPY及MOVE。<br>如果你写一个WebDAV的Servlet，你不必使用doLock()和doCopy()方法。你必须写自己的service()方法及分派request.getMethod()方法。正由于这种变化，你不必管理系统的安全性。<br>去除限制：<br><br>Servlet2.5去除了关于错误处理和回话跟踪的一些限制。对于错误处理，Servlet2.5之前，配置在&lt;error- page&gt;中的错误处理页面不能通过调用setStatus()方法来修改触发他们的错误代码，而Servlet2.5减弱了这一规范。这样的规范的产生于这样的观点，就是错误页面的工作是指出每个错误而不是修改错误。但是，实际使用中，错误页面不只是用于指出错误，而是还能做更多的事情，或许可以代替在线帮助来帮助用户解决问题。这个规范将不再限制错误页面所产生的反馈信息。<br><br>对于会话跟踪，Servlet2.5之前，调用RequestDispatcher.include()的Servlet不能设置响应的标题头，而 Servlet2.5减弱了这一规范。原规范的目的是使内部的Servlets限制在自己的页面空间中，不可以影响外部的页面。现在这个规范已经减弱，允许在内部的Servlet中使用request.getSession()命令，这个命令可以悄悄地创建一个会话跟踪cookie的标题头。逻辑上要求限制内部的资源，但逻辑上也要求这些限制不应该取消其启动session的这一功能。这个变动对于Portlet规范来说显得尤其重要。作用是：如果响应已经有效，则getSession()命令就会抛出一个IllegalStateException(异常)，而在此之前，就没有这个功能。<br><br><strong>优化：</strong><br>最近，新的规范优化了一些实例，使得Servlets更加方便而且保证了更好地按要求工作。<br><br><strong>终止响应：</strong><br>第一处优化细小又深奥，但做为规范中的一个例子还有蛮有趣的。Servlet2.4规范规定响应在这几种情况下应该是有效的，包括：在响应的 setContentLength方法中内容已经明确说明，以及内容已经写进了响应中。这种情况只有你的代码像下面这样才可以使响应重新定向：<br><br>response.setHeader("Host",&nbsp;"localhost")；<br>response.setHeader("Pragma",&nbsp;"no-cache")；<br>response.setHeader("Content-Length",&nbsp;"0")；<br>response.setHeader("Location",&nbsp;"http://www.apache.org")；<br><br>Servlet技术忽略特定区域的标题头，因为内容满足0字节长度，响应就会立即生效。而在它开始之前，响应就已失效了！Servlet容器通常拒绝执行这种行为，而Servlet2.5版本增加了&#8220;长度必须大于0&#8221;这个原则。<br>实例编码：<br><br>Servlet2.4规范规定必须在调用request.getReader()方法之前调用 request.setCharacterEncoding()方法。但是，如果你忽略这个原则而在其之后去调用 request.setCharacterEncoding()方法，那么会产生什么后果，这个问题规范里并没有说。为了简便，现在消除这种情况！<br>Cross-context&nbsp;sessions(不同上下文目录间的会话)：<br>最近，关于Cross-context会话处理的规则已经明确说明。当Servlets指派从一个上下文到其他上下文的请求时，这个规则就发挥了作用??在目标调用过程中，包括哪些会话。这个版本的出现使得一个上下文目录的主页里的portlets可以通过几种内部的命令来对别的上下文目录里的 portlets起作用。Servlet2.5明确指出一个上下文目录里的资源可以访问其他上下文目录的session(会话)，而不用考虑这个请求从哪里开始的。这意味着portlets可以脱离主页的范围而在自己的范围里运行，而且这个规范还会应用在不兼容的Serlvet容器中。<br>期待：<br><br>由于Servlet2.5版本要保持一些旧的性质，几个大的概念不得不延后到下一个阶段。它们包括：<br>"新的输入/输出(NIO)支持：使NIO通道更有利于Servlets进行客户端通信成为可能。<br>"过滤器wrap-under或wrap-over语义：有时用过滤器包装请求，和/或者响应对象去修改方法行为或者启用新的方法。当把这种包装和服务器对请求和响应的包装结合起来时，又应该怎么包装在一起？<br>"用于欢迎的Servlets文件：做为索引应该充当欢迎作用的文件吗？在此之前，这个回答是肯定的。但是规范没有明确说明如何使用这个功能，尤其在没有索引的情况下。<br>"用于欢迎的文件的分派规则：如何分派欢迎文件，这个细节并没有完全说明，而是遗留了一些开放的缺口来应对不兼容问题。<br>"登陆后选择默认页面：如果用户通过他们的书签访问Servlet的登陆页面，那么在成功登陆后页面应该转向哪里呢？这个问题至今尚未明确说明。<br>"用户的主题日志：在通过网站正确地注册之后，不通过传统地登陆方式没有办法使Servlet信任用户。<br>结束语：<br>如果抛开注释来看Servlet2.5的变化，可见在配置文件web.xml中去除了一些限制，是有利的，同时又优化了实例行为使其更适合更便于开发Web系统(网页)。<br>Servlet2.5中注释的作用更加戏剧化。Servlets本身不能声明注释类型的变量，甚至性能弱的Servlet容器都不支持注释。然而在 JEE5环境下的Servlets编写者可以看到，通过公共的注释及EJB3.0和JAX-WS2.0规范而引入的注释类型会对代码产生很大变化，并且这也将对Servlet如何管理外部资源，对象的持久化及EJB的构成产生重大影响</p>
<p>J2EE的两种重要的表现层技术JSP和JSF发布了新技术规范的预览版本，其中最重要的一点是两者将表达式语言（Expression Language，EL）部分合二为一。在不久的将来，这两种技术有可能更进一步地彼此融合，成为一种统一的表现层技术。然而在J2EE社群的普遍观点中，如果单单作为一种视图技术，JSP并不是最佳的选择，Velocity和XSLT等基于模板的视图技术通常比JSP更方便；而基于组件的JSF也面临广泛的信任危机。两者的组合是否能得到业界的认可，还需要时间的检验。</p>
<p><strong>jsp 2.1</strong></p>
<p><br>&nbsp;&nbsp;&nbsp; 我们很高兴向大家宣告，JavaServer Pages、JSR-245下开发的Faces.JavaServer Pages（JSP）2.1和JSR-252下开发的JavaServer Faces（Faces）1.2的新版规范的Early Draft Review发布。</p>
<p>&nbsp;&nbsp;&nbsp; JSP 2.1把Expression Language（EL）输出到它自己各自分离的文档中，在技术上，这些文档是JSP规范的子文档。这些统一的EL规范定义了一个更高层的java 包，javax.el。这个包与使用它的技术之间完全独立，并且允许此技术将自身插入EL处理过程。更改的JSP规范遵从使用标准化EL的规范。</p>
<p>&nbsp;&nbsp;&nbsp; 对于前面提到的JSR-252，这个规范并没什么新特性。Faces 1.2支持新的标准化EL，还包含一些bug修复的相关规范。</p>
<p>&nbsp;&nbsp;&nbsp; Faces和JSP在JSRs下的结盟带来了一些新功能，也为将来的发展打下了坚实的基础。例如，在同时使用Faces和JSP的web应用中，网页仅使用JSP（不包含任何faces内容）来访问Managed Beans成为可能。在JSP规范的附录E中和Faces规范的前言中都可以看到更改内容的细节。</p>
</div>
<img src ="http://www.blogjava.net/simie/aggbug/127500.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/simie/" target="_blank">和田雨</a> 2007-07-02 12:20 <a href="http://www.blogjava.net/simie/archive/2007/07/02/127500.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>servlet规范要求：request的缺省编码必须是iso-8859-1</title><link>http://www.blogjava.net/simie/archive/2007/07/02/127498.html</link><dc:creator>和田雨</dc:creator><author>和田雨</author><pubDate>Mon, 02 Jul 2007 04:19:00 GMT</pubDate><guid>http://www.blogjava.net/simie/archive/2007/07/02/127498.html</guid><wfw:comment>http://www.blogjava.net/simie/comments/127498.html</wfw:comment><comments>http://www.blogjava.net/simie/archive/2007/07/02/127498.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/simie/comments/commentRss/127498.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/simie/services/trackbacks/127498.html</trackback:ping><description><![CDATA[看到很多文章在问和答关于java网页汉字乱码的情况，有些甚至认为这是servlet包容器实现上的错误。<br>可是如果读过servlet规格说明书，关于java网页编码的问题就应该迎刃而解了。<br><br>编写java网页（servlet\jsp），需要关心response(反馈给客户端的页面)和request（来自客户端的数据）的编码问题。<br><br>response的编码可以直接用代码实现。而request的编码怎么办呢？<br>以下是servlet规范书上的文字（我粗略翻译一下吧，不怕见笑）：<br><br>-- 整理自&lt;Java Servlet Specification Version 2.3&gt; SRV.4.9 --<br><br>当前,很多浏览器并不发送带有&#8220;Content-Type&#8221;头信息的字符编码限定符，而由读取HTTP请求的代码来决定字符的编码方式。如果客户端请求未定义编码限定符，则包容器（如tomcat）用于创建request reader和分析POST数据的request的缺省编码方式必须是&#8220;ISO-8859-1&#8221;。然而，为了向开发者指明客户端没有发送字符编码信息的情况，包容器对getCharacterEncoding方法返回null。<br><br>如果客户端不设置字符编码方式，并且request不是按照以上缺省编码方式（iso-8859-1）来编码，则会发生问题。为了解决这个问题，在接口ServletRequest中加入了一个新的方法setCharacterEncoding(String enc)。开发者可以调用这个方法来替换包容器提供的缺省字符编码方式。但是，必须在从request中分析任何POST数据或者读取任何输入之前，调用这个方法。一旦数据已被读取，则调用这个方法将不会影响编码方式。
<img src ="http://www.blogjava.net/simie/aggbug/127498.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/simie/" target="_blank">和田雨</a> 2007-07-02 12:19 <a href="http://www.blogjava.net/simie/archive/2007/07/02/127498.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Servlet过滤器</title><link>http://www.blogjava.net/simie/archive/2007/07/02/127497.html</link><dc:creator>和田雨</dc:creator><author>和田雨</author><pubDate>Mon, 02 Jul 2007 04:13:00 GMT</pubDate><guid>http://www.blogjava.net/simie/archive/2007/07/02/127497.html</guid><wfw:comment>http://www.blogjava.net/simie/comments/127497.html</wfw:comment><comments>http://www.blogjava.net/simie/archive/2007/07/02/127497.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/simie/comments/commentRss/127497.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/simie/services/trackbacks/127497.html</trackback:ping><description><![CDATA[一、Servlet过滤器的概念：<br>***************************************************************************************<br>Servlet过滤器是在Java&nbsp;Servlet规范2.3中定义的，它能够对Servlet容器的请求和响应对象进行检查和修改。　　　<br><br>Servlet过滤器本身并不产生请求和响应对象，它只能提供过滤作用。Servlet过期能够在Servlet被调用之前检查Request对象，修改Request&nbsp;Header和Request内容；在Servlet被调用之后检查Response对象，修改Response&nbsp;Header和Response内容。<br><br>Servlet过期负责过滤的Web组件可以是Servlet、JSP或者HTML文件。　<br>***************************************************************************************<br><br><br>二、Servlet过滤器的特点：<br>***************************************************************************************<br>A．Servlet过滤器可以检查和修改ServletRequest和ServletResponse对象<br>B．Servlet过滤器可以被指定和特定的URL关联，只有当客户请求访问该URL时，才会触发过滤器<br>C．Servlet过滤器可以被串联在一起，形成管道效应，协同修改请求和响应对象<br>***************************************************************************************<br><br><br>三、Servlet过滤器的作用：<br>***************************************************************************************<br>A．查询请求并作出相应的行动。<br>B．阻塞请求-响应对，使其不能进一步传递。<br>C．修改请求的头部和数据。用户可以提供自定义的请求。<br>D．修改响应的头部和数据。用户可以通过提供定制的响应版本实现。<br>E．与外部资源进行交互。<br>***************************************************************************************<br><br><br>四、Servlet过滤器的适用场合：<br>***************************************************************************************<br>A．认证过滤<br>B．登录和审核过滤<br>C．图像转换过滤&nbsp;<br>D．数据压缩过滤&nbsp;<br>E．加密过滤&nbsp;<br>F．令牌过滤&nbsp;<br>G．资源访问触发事件过滤&nbsp;<br>H．XSL/T过滤&nbsp;<br>I．Mime-type过滤<br>***************************************************************************************<br><br><br>五、Servlet过滤器接口的构成：<br>***************************************************************************************<br>所有的Servlet过滤器类都必须实现javax.servlet.Filter接口。这个接口含有3个过滤器类必须实现的方法：<br><br>A.init(FilterConfig)：<br>这是Servlet过滤器的初始化方法，Servlet容器创建Servlet过滤器实例后将调用这个方法。在这个方法中可以读取web.xml文件中Servlet过滤器的初始化参数<br><br>B.doFilter(ServletRequest,ServletResponse,FilterChain)：<br>这个方法完成实际的过滤操作，当客户请求访问于过滤器关联的URL时，Servlet容器将先调用过滤器的doFilter方法。FilterChain参数用于访问后续过滤器<br><br>B.destroy()：<br>Servlet容器在销毁过滤器实例前调用该方法，这个方法中可以释放Servlet过滤器占用的资源<br>***************************************************************************************<br><br><br>六、Servlet过滤器的创建步骤：<br>***************************************************************************************<br>A．实现javax.servlet.Filter接口<br>B．实现init方法，读取过滤器的初始化函数<br>C．实现doFilter方法，完成对请求或过滤的响应<br>D．调用FilterChain接口对象的doFilter方法，向后续的过滤器传递请求或响应<br>E．销毁过滤器<br>***************************************************************************************<br><br><br>七、Servlet过滤器对请求的过滤：<br>***************************************************************************************<br>A．Servlet容器创建一个过滤器实例<br>B．过滤器实例调用init方法，读取过滤器的初始化参数<br>C．过滤器实例调用doFilter方法，根据初始化参数的值判断该请求是否合法<br>D．如果该请求不合法则阻塞该请求<br>E．如果该请求合法则调用chain.doFilter方法将该请求向后续传递<br>***************************************************************************************<br><br><br>八、Servlet过滤器对响应的过滤：<br>***************************************************************************************<br>A．过滤器截获客户端的请求<br>B．重新封装ServletResponse，在封装后的ServletResponse中提供用户自定义的输出流<br>C．将请求向后续传递<br>D．Web组件产生响应<br>E．从封装后的ServletResponse中获取用户自定义的输出流<br>F．将响应内容通过用户自定义的输出流写入到缓冲流中<br>G．在缓冲流中修改响应的内容后清空缓冲流，输出响应内容<br>***************************************************************************************<br><br>九、Servlet过滤器的发布：<br>***************************************************************************************<br>A．发布Servlet过滤器时，必须在web.xml文件中加入&lt;filter&gt;元素和&lt;filter-mapping&gt;元素。<br><br>B．&lt;filter&gt;元素用来定义一个过滤器：<br>属性&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;含义<br>filter-name&nbsp;&nbsp;&nbsp;&nbsp;指定过滤器的名字<br>filter-class&nbsp;&nbsp;&nbsp;&nbsp;指定过滤器的类名<br>init-param&nbsp;&nbsp;&nbsp;&nbsp;为过滤器实例提供初始化参数，可以有多个<br><br>C．&lt;filter-mapping&gt;元素用于将过滤器和URL关联：<br>属性&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;含义<br>filter-name&nbsp;&nbsp;&nbsp;&nbsp;指定过滤器的名字<br>url-pattern&nbsp;&nbsp;&nbsp;&nbsp;指定和过滤器关联的URL，为&#8221;/*&#8221;表示所有URL<br>***************************************************************************************<br><br><br>十一、Servlet过滤器使用的注意事项<br>***************************************************************************************<br>A．由于Filter、FilterConfig、FilterChain都是位于javax.servlet包下，并非HTTP包所特有的，所以其中所用到的请求、响应对象ServletRequest、ServletResponse在使用前都必须先转换成HttpServletRequest、HttpServletResponse再进行下一步操作。<br><br>B．在web.xml中配置Servlet和Servlet过滤器，应该先声明过滤器元素，再声明Servlet元素<br><br><br>C．如果要在Servlet中观察过滤器生成的日志，应该确保在server.xml的localhost对应的&lt;host&gt;元素中配置如下&lt;logger&gt;元素：<br>&lt;Logger&nbsp;className&nbsp;=&nbsp;&#8220;org.apache.catalina.logger.FileLogger&#8221;<br>directory&nbsp;=&nbsp;&#8220;logs&#8221;prefix&nbsp;=&nbsp;&#8220;localhost_log.&#8221;suffix=&#8221;.txt&#8221;<br>timestamp&nbsp;=&nbsp;&#8220;true&#8221;/&gt;<br>***************************************************************************************
<img src ="http://www.blogjava.net/simie/aggbug/127497.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/simie/" target="_blank">和田雨</a> 2007-07-02 12:13 <a href="http://www.blogjava.net/simie/archive/2007/07/02/127497.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>