﻿<?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>IT博客-火炏炎焱燚</title><link>http://www.cnitblog.com/afa202/</link><description>火炏炎焱燚</description><language>zh-cn</language><lastBuildDate>Wed, 29 Apr 2026 05:58:56 GMT</lastBuildDate><pubDate>Wed, 29 Apr 2026 05:58:56 GMT</pubDate><ttl>60</ttl><item><title>热键设计</title><link>http://www.cnitblog.com/afa202/archive/2010/04/26/65613.html</link><dc:creator>火炏炎焱燚</dc:creator><author>火炏炎焱燚</author><pubDate>Mon, 26 Apr 2010 06:18:00 GMT</pubDate><guid>http://www.cnitblog.com/afa202/archive/2010/04/26/65613.html</guid><wfw:comment>http://www.cnitblog.com/afa202/comments/65613.html</wfw:comment><comments>http://www.cnitblog.com/afa202/archive/2010/04/26/65613.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/afa202/comments/commentRss/65613.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/afa202/services/trackbacks/65613.html</trackback:ping><description><![CDATA[<p>-----------------热键注册类<br><br><br>using System;<br>using System.Collections.Generic;<br>using System.Text;<br>using System.Windows.Forms;<br>using System.Runtime.InteropServices;</p>
<p><br>namespace Workflow.Frame<br>{<br>&nbsp;&nbsp;&nbsp; /// &lt;summary&gt;<br>&nbsp;&nbsp;&nbsp; /// 热键注册类<br>&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br>&nbsp;&nbsp;&nbsp; public class HotKey<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //如果函数执行成功，返回值不为0。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //如果函数执行失败，返回值为0。要得到扩展错误信息，调用GetLastError。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [DllImport("user32.dll", SetLastError = true)]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static extern bool RegisterHotKey(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IntPtr hWnd,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //要定义热键的窗口的句柄<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int id,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //定义热键ID（不能与其它ID重复）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; KeyModifiers fsModifiers,&nbsp;&nbsp; //标识热键是否在按Alt、Ctrl、Shift、Windows等键时才会生效<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Keys vk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //定义热键的内容<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; );<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [DllImport("user32.dll", SetLastError = true)]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static extern bool RegisterHotKey(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IntPtr hWnd,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //要定义热键的窗口的句柄<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int id,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //定义热键ID（不能与其它ID重复）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; KeyModifiers fsModifiers,&nbsp;&nbsp; //标识热键是否在按Alt、Ctrl、Shift、Windows等键时才会生效<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; KeyModifiers vk,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //定义热键的内容<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Keys vkk<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; );</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [DllImport("user32.dll", SetLastError = true)]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static extern bool UnregisterHotKey(<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IntPtr hWnd,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //要取消热键的窗口的句柄<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //要取消热键的ID<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; );</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //定义了辅助键的名称（将数字转变为字符以便于记忆，也可去除此枚举而直接使用数值）<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [Flags()]<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public enum KeyModifiers<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; None = 0,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Alt = 1,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Ctrl = 2,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Shift = 4,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WindowsKey = 8<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; }<br>&nbsp;<br>}<br><br><br>-----------------------from中注册，及消息处理方式-------<br><br>private void MainForm_Activated(object sender, EventArgs e)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //注册热键Shift+S，Id号为100。HotKey.KeyModifiers.Shift也可以直接使用数字4来表示。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HotKey.RegisterHotKey(Handle, 100, HotKey.KeyModifiers.Shift, Keys.S);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //注册热键Ctrl+B，Id号为101。HotKey.KeyModifiers.Ctrl也可以直接使用数字2来表示。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HotKey.RegisterHotKey(Handle, 101, HotKey.KeyModifiers.Ctrl, Keys.B);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //注册热键Alt+D，Id号为102。HotKey.KeyModifiers.Alt也可以直接使用数字1来表示。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HotKey.RegisterHotKey(Handle, 102, HotKey.KeyModifiers.Alt, Keys.D);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //注册热键Alt+D，Id号为102。HotKey.KeyModifiers.Alt也可以直接使用数字1来表示。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HotKey.RegisterHotKey(Handle, 103, HotKey.KeyModifiers.Ctrl|HotKey.KeyModifiers.Alt, Keys.X);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void MainForm_Leave(object sender, EventArgs e)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //注销Id号为100的热键设定<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HotKey.UnregisterHotKey(Handle, 100);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //注销Id号为101的热键设定<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HotKey.UnregisterHotKey(Handle, 101); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //注销Id号为102的热键设定<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HotKey.UnregisterHotKey(Handle, 102);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 监视Windows消息<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 重载WndProc方法，用于实现热键响应<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; protected override void WndProc(ref Message m)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const int WM_HOTKEY = 0x0312;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //按快捷键 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (m.Msg)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case WM_HOTKEY:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (m.WParam.ToInt32())<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 100:&nbsp;&nbsp;&nbsp; //按下的是Shift+S<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //此处填写快捷键响应代码&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 101:&nbsp;&nbsp;&nbsp; //按下的是Ctrl+B<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //此处填写快捷键响应代码<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 102:&nbsp;&nbsp;&nbsp; //按下的是Alt+D<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //此处填写快捷键响应代码<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 103:&nbsp;&nbsp;&nbsp; //按下的是Alt+D<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //此处填写快捷键响应代码<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; base.WndProc(ref m);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<img src ="http://www.cnitblog.com/afa202/aggbug/65613.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/afa202/" target="_blank">火炏炎焱燚</a> 2010-04-26 14:18 <a href="http://www.cnitblog.com/afa202/archive/2010/04/26/65613.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>地址重写  转载</title><link>http://www.cnitblog.com/afa202/archive/2009/08/12/60763.html</link><dc:creator>火炏炎焱燚</dc:creator><author>火炏炎焱燚</author><pubDate>Wed, 12 Aug 2009 09:04:00 GMT</pubDate><guid>http://www.cnitblog.com/afa202/archive/2009/08/12/60763.html</guid><wfw:comment>http://www.cnitblog.com/afa202/comments/60763.html</wfw:comment><comments>http://www.cnitblog.com/afa202/archive/2009/08/12/60763.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/afa202/comments/commentRss/60763.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/afa202/services/trackbacks/60763.html</trackback:ping><description><![CDATA[<p>1.1. 概要<br>分析如何使用微软提供的ASP.NET来对动态产生的URL地址进行网址重写。网址重写是实现一种截取网址请求并将其进行处理后重新指向到一个指定的网址的过程。作者本人在对各种实现网址重写的技术进行研究和探讨后得出的经验和方法，希望能对您有所帮助。 <br>1.2. 内容简介<br>稍微花点时间看一看你做的网站里头的URL地址，你看到类似这样的地址吗<a href="http://yoursite.com/info/dispEmployeeInfo.aspx?EmpID=459-099&amp;type=summary">http://yoursite.com/info/dispEmployeeInfo.aspx?EmpID=459-099&amp;type=summary</a> ？也许你会出于某种目的把大量的页面文件从一个目录甚至一个网站转移到其他地方，而许多访问者出于个人兴趣或者研究目的之前就已经将原有网址收藏了起来， 如果这时他从收藏夹打开该页面的时候发现这已经是坏链了。本文旨在介绍如何使用网址重写将那些&#8220;难看&#8221;的网址转换成比较有实际意义的网址，使其便于记忆。例如将<a href="http://yoursite.com/info/dispEmployeeInfo.aspx?EmpID=459-099&amp;type=summary">http://yoursite.com/info/dispEmployeeInfo.aspx?EmpID=459-099&amp;type=summary</a>转换成如下地址：<a href="http://yoursite.com/">http://yoursite.com/</a> dispEmployeeInfo/459-099/summary.html 。我们甚至发现网址重写技术可以解决令人头疼的404错误，或者说它可以创建一个智能化的404错误解决方案。<br>如上所述，网址重写是实现一种截取网址请求并将其进行处理后重新指向到一个指定的网址的过程。在网址重写执行的期间，相应处理程序处理被请求的网址，从中提取出相关的值，然后重新指向一个新的指定地址。例如：由于一次网站目录调整，原有的 /people/ 子目录下的所有网页全部移动到/info/employees/目录，原访问者从收藏夹或者其他什么地方点击链接发出访问/people/目录下的文件的请求时，你肯定希望他还是能通过原有地址看到和原来相同的页面，但实际上看到的却是网址重写指向的新目录下的相应文件。<br>在老版本ASP中，使用网址重写技术的途径很少，要么写一个ISAPI过滤器，要么购买第三方厂商提供的网址重写组件，然而在微软提供的ASP.NET下你可以通过多种方法很简单地开发出自己的网址重写软件，以满足自己各种不同的需要。本文将和你一起讨论这门针对ASP.NET开发人员的实现网址重写的技术，然后举一些网址重写实际应用的例子。在我们深入探讨网址重写技术的细节之前，我们先看一下日常使用网址重写技术实现的场景。</p>
<p>1.3. 网址重写的一般用途<br>创建一个数据操作的ASP.NET程序最常见的就是一个aspx页面后面带上一些查询参数集合。例如在设计一个电子商务网站的时候，假定你设计了一项功能允许用户浏览待售的商品，为了更加方便操作，你设计了一个页面displayCategory.aspx将商品按照给定的分类显示，那么该分类下的商品显示页面上应该在页面文件对应网址后面加上了一个商品分类的查询参数，例如用户要查询待售的&#8220;装饰品&#8221;，在数据库中所有的装饰品数据对应的分类编号CategoryID的值为5，那么用户会访问如下网址：<a href="http://yoursite.com/displayCategory.aspx?CategoryID=5">http://yoursite.com/displayCategory.aspx?CategoryID=5</a>。<br>创建一个包含类似这样网址的网站最终有两种结果，首先从最终用户的角度来观察，<a href="http://yoursite.com/displayCategory.aspx?CategoryID=5">http://yoursite.com/displayCategory.aspx?CategoryID=5</a> 这个网址有些杂乱，可行性分析专家Jakob Neilson（主页：<a href="http://useit.com/">http://useit.com/</a>） 建议选择网址显示方式时候考虑如下要求（参考网址：<a href="http://www.useit.com/alertbox/990321.html">http://www.useit.com/alertbox/990321.html</a>）：<br>&nbsp;&nbsp;&nbsp;&nbsp; ● 是否简短<br>&nbsp;&nbsp;&nbsp;&nbsp; ● 是否易于输入<br>&nbsp;&nbsp;&nbsp;&nbsp; ● 是否将站点结构形象化<br>&nbsp;&nbsp;&nbsp;&nbsp; ● 是否具有隐蔽性，也就是让用户通过一个虚拟的看似有意义的导航地址访问指向该地址<br>我想还应该在上述列表中再增加一条：是否便于记忆。<a href="http://yoursite.com/displayCategory.aspx?CategoryID=5">http://yoursite.com/displayCategory.aspx?CategoryID=5</a> 这个地址没有一个地方符合Neilson标准的任何一条，也不便于记忆。当然，对于有经验的网络开发专家来说，他们很熟悉这种键值对构成的查询参数结构体系，然而对于普通用户来说输入这些带有参数的网址实在是太麻烦了。<br>一种较好的方法就是使用一种比较直观且容易记忆的方式来将网址表示为：<a href="http://yoursite.com/products/Widgets">http://yoursite.com/products/Widgets</a> 乍一看很容易就会推断这个网址所对应的内容极有可能会是显示装饰品（Widgets）信息，这个网址就变得更加容易记忆和传播！然后我告诉我的同事：&#8220;请查看这个网址：<a href="http://yoursite.com/products/widgets">http://yoursite.com/products/widgets</a> &#8221;不用我说第二遍，她可能一次就把地址敲到浏览器上了（你也可以在亚马逊（Amazon.com）的网站上这样尝试一下）。很快就浏览器上就列出了装饰品（Widgets）的内容。这里&#8220;隐蔽性&#8221;表示：用户可以自行变更网址的结尾，例如输入：<a href="http://yoursite.com/products">http://yoursite.com/products</a> 就能看到全部分类相关的商品列表或者列出所有相关商品分类目录列表。<br>注：用上述简单的变更网址内容的方法来构思一下如今的比较流行的Blog网站生成的网址。例如：要查询2004年1月28日所发的帖子，只需输入 <a href="http://someblog.com/2004/01/28">http://someblog.com/2004/01/28</a>&nbsp; 即可，如果将网址裁减为 <a href="http://someblog.com/2004/01">http://someblog.com/2004/01</a> 则显示 2004年1月份的帖子 ，同样将月份裁减掉得到 <a href="http://someblog.com/2004">http://someblog.com/2004</a> 则显示出2004年全年所发的帖子。<br>网址重写技术除了用于将复杂的网址简单化之外，它还能用于处理因网站目录调整或者其他原因导致产生大量的无效链接和过期书签。 <br>1.4. 当一个Web请求传送到IIS会发生什么？<br>在探讨如何实现网址重写这项技术之前，很有必要了解一下IIS是处理所接收的Web请求的机制。当一个Web请求到达IIS Web服务器时，IIS会根据所请求的文件后缀名来决定如何处理该请求，IIS可以处理诸如HTML页面、图片、静态内容，或者将请求转发给ISAPI应用程序，由该ISAPI应用程序处理后生成HTML静态内容返回给IIS，最后由IIS将请求结果发送回给客户端。（一个ISAPI应用程序就是一套编译好能随时在后台运行的类库，它的任务就是根据请求生成相关的内容。）<br>例如：如果IIS接收到一个对Info.asp的请求，它会将该请求转交给asp.dll来处理，该ISAPI应用程序调出并执行所请求的ASP页面，然后把生成的HTML代码返回给IIS，IIS最后把内容发送回请求客户端。对于ASP.NET页面，IIS则将请求转交给名为aspnet_isapi.dll的ISAPI应用程序来处理，该ISAPI应用程序调用托管的ASP.NET工作进程来处理该请求，并将生成的HTML代码返回给请求客户端。<br>你可以自定义IIS，将某一类扩展名映射到指定的ISAPI应用程序，图一显示了IIS管理工具中的应用程序配置对话框。</p>
<p><br>图一．已配置的文件扩展名映射</p>
<p>&nbsp;</p>
<p><br>关于对IIS如何管理所接收的请求的详细探讨有些超出本文内容，想了解的更详细的话可以参考Michele Leroux Bustamante的著作Inside IIS and ASP.NET（深入研究IIS与ASP.NET），重要的是要了解ASP.NET引擎只负责处理对扩展名已经被正确配置映射到aspnet_isapi.dll的网络请求。</p>
<p>1.5. 用ISAPI过滤器来分析请求<br>除了将请求的文件扩展名映射到相应的ISAPI应用程序外，IIS还执行一些其他工作。例如IIS还主动对发出请求的客户端用户进行授权，并判断已授权用户是否对其请求的文件拥有访问权限，在一个请求过程的全部生命期内，IIS的处理经历了几个阶段，在每一个阶段IIS都生成一个事件，而该事件可以被ISAPI过滤器实时操控的。<br>如同ISAPI应用程序一样，ISAPI过滤器也是一块块安装在Web服务器上的非托管代码。ISAPI应用程序用于对所接收的特定文件类型做出响应，而ISAPI过滤器含有对IIS生成的事件做出响应的代码（contain Code），甚至可以编辑进出的数据。ISAPI也含有众多应用程序，包括：<br>&nbsp;&nbsp;&nbsp; &#183; 权限控制与授权（Authentication and Authorization）<br>&nbsp;&nbsp;&nbsp; &#183; 日志记录与监视（Logging and Monitoring）<br>&nbsp;&nbsp;&nbsp; &#183; HTTP内容压缩（HTTP Compression）<br>&nbsp;&nbsp;&nbsp; &#183; 网址重写（URL Rewriting）<br>本文所探讨的用ASP.NET实现的网址重写技术就是基于ISAPI过滤器用于网址重写的技术内容，然而我们仍然要讨论一下究竟是使用ISAPI过滤器还是使用ASP.NET应用程序提供的技术来实现网址重写技术。</p>
<p><br>1.6. 当一个请求传入ASP.NET引擎的时候会发生什么？<br>ASP.NET问世之前，在IIS Web服务器上的网址重写功能需要通过ISAPI过滤器来实现，自从这个家伙问世后我们就能通过ASP.NET来实现URL重写了，因为ASP.NET的解释引擎与IIS有极大的相似之处，产生这些相似性主要是因为ASP.NET：<br>&nbsp;&nbsp;&nbsp; &#183; 在处理接收的请求的生命期内也会产生事件；<br>&nbsp;&nbsp;&nbsp; &#183; 允许任意数量的HttpModule操控产生的事件，这与IIS中的ISAPI过滤器类似；<br>&nbsp;&nbsp;&nbsp; &#183; 将请求的资源委托给HttpHandler处理，这与IIS中的ISAPI应用程序类似。<br>和IIS一样，在一个请求的整个生命期内，ASP.NET对该请求的处理状态发出的状态改变信号引发相应的事件。例如：BeginRequest事件在ASP.NET开始响应客户端请求之始引发；AuthenticateRequest事件在ASP.NET确立用户身份后引发，当然还有诸如AuthorizeRequest，ResolveRequestCache和EndRequest等其它很多事件，这些都是System.Web.HttpApplication类下的事件，更多信息请参考技术文档中的类HttpApplication概要（HttpApplication Class Overview）。<br>如上所述，可以创建ISAPI过滤器并用于相应IIS引发的事件，同理，ASP.NET也提供了HttpModule用于响应ASP.NET引擎引发的事件，一个ASP.NET应用程序通过配置可以拥有多个HttpModule。ASP.NET引擎每处理一个请求，便初始化一个相应配置好的HttpModule，并允许它针对请求处理期间引发的事件生成相应的事件委托。事实上ASP.NET引擎处理每一个请求调用大量的事件委托。FormsAuthenticationModule就是众多内嵌HttpModule中的一个，它首先检查是否使用表单授权，如果是的话，它将检查用户是否已授权，如果没有授权则自动把用户重定向到指定的登录页面。<br>回忆在IIS中，一项请求最后被转交给一个ISAPI应用程序处理，该应用程序针对每一项请求进行处理并返回相应的数据。例如，客户端发出一个访问经典ASP页面的请求，IIS将该请求转交给asp.dll程序处理，asp.dll针对该请求执行asp页面内容，并返回HTML编码。ASP.NET也使用了类似的手法，ASP.NET引擎在将这些HttpModule初始化后，判断并决定调用相应的HttpModule来处理该请求。<br>所有通过ASP.NET引擎解析的请求最终被送交一个HttpHandler或者HttpHandlerFactory（一个HttpHandler只是简单地返回一个用于处理该请求的HttpHandler的实例。）最终的委托呈现并响应所请求的HTML编码，并发送回IIS，IIS则将HTML返回给请求客户端。<br>ASP.NET包含许多HttpHandler，例如，PageHandlerFactory是用于呈现ASP.NET页面内容，WebServiceHandlerFactory用于呈现ASP.NET Web服务的SOAP数据包，TraceHandler用于将ASP.NET请求资源的HTML标记写入trace.axd。<br>图二描绘了一个针对ASP.NET资源的请求所经过的处理流程。首先，IIS接收到该请求并将其转交给aspnet_isapi.dll。其次，ASP.NET引擎将一些HttpModule初始化。最后，最终的HttpHandler被调用，生成相应的标记语言，并将其返回给IIS，最终返回到请求客户端。</p>
<p><br>图二．IIS和ASP.NET对请求的处理过程</p>
<p><br>1.7. 创建并注册自定义HttpModule和HttpHandler<br>创建自定义HttpModule的工作相对较简单，它包括一个实现当前接口的托管类，HttpModule必须实现System.Web.IHttpModule接口，同样HttpHandler和HttpHandlerFactory必须分别实现System.Web.IHttpHandler接口和System.Web.IhttpHandlerFactory接口。有关创建HttpHandler和HttpModule的细节已经超出本书范围，要了解更多详情请参阅Mansoor Ahmed Siddiqui的文章《HttpHandlers and HTTP modules in ASP.NET》（ASP.NET中的HttpHandler和HttpModule）。<br>一旦HttpModule和HttpHandler被创建后，必须向Web应用程序注册。如果要向整个Web服务器HttpModule和HttpHandler只需简单的写入machine.config文件；如果是由指定的Web应用程序调用则需在该程序的web.config配置文件中添加几行XML标记。<br>例如，要向指定的Web应用程序注册HttpModule和HttpHandler，只需向该Web应程序的web.config配置文件中configuration\System.Web节中添加下列几行：</p>
<p>&lt;HttpModules&gt;<br>&nbsp;&nbsp;&nbsp; &lt;add type="type" name="name" /&gt;<br>&lt;/HttpModules&gt;<br>其中type属性为HttpModule的标识号和类库名称，name属性则为该模块取一个较为友好的名称方便在Global.asax调用。<br>HttpHandler和HttpHandlerFactory则是在web.config文件中configuration\System.Web节中添加&lt;httpHandler&gt;标记，例如：</p>
<p>&lt;httpHandlers&gt;<br>&nbsp;&nbsp;&nbsp; &lt;add verb="verb" path="path" type="type" /&gt;<br>&lt;/HttpModules&gt;<br>回忆上文，ASP.NET对每一个接收到的请求指派相应的HttpHandler来处理并呈现相应内容，该指派决定于所接收请求的verb和path的内容，verb为HTTP请求的类型：GET或者POST，path则为请求的文件的路径和文件名。如果我们打算用一个HttpHandler来处理所有GET类型和POST类型的并且文件扩展名为.scott的内容，可以在web.config相应配置节中加入下列标记：</p>
<p>&lt;httpHandlers&gt;<br>&nbsp;&nbsp;&nbsp; &lt;add varb="*" path=".scott" type="type" /&gt;<br>&lt;/httpHandlers&gt;<br>其中type是我们定义的HttpHandler的类型。<br>注意：在注册HttpHandler的时候必须注意HttpHandler所使用的文件扩展名必须已经在IIS中做指向ASP.NET引擎的映射，在上面.scott扩展名的例子中，如果我们所使用的.scott扩展名如果没有在IIS中做指向ASP.NET引擎的映射的话，假定对foo.scott文件发出请求，该请求将导致IIS将foo.scott文件内容直接呈现给客户端，为了能够让HttpHandler处理该请求，必须将.scott扩展名在IIS中做指向ASP.NET引擎的映射，之后IIS才能正确地将.scott的请求转交给相应的HttpHandler。<br>有关HttpModule和HttpHandler更详细的内容请参阅MSDN中&lt;HttpModules&gt;节和&lt;httpHandlers&gt;节的文档信息。<br>&lt;HttpModules&gt;文档参考；<br>&lt;httpHandlers&gt;文档参考。</p>
<p>1.8. 实现网址重写<br>网址重写技术不但可以在IIS Web服务器一级通过ISAPI过滤器实现，而且还可以在ASP.NET一级通过HttpModule或者HttpHandler实现。本文主要关注在ASP.NET一级实现网址重写技术，所以此时不必关注在ISAPI应用程序中实现网址重写的技术细节，而且有很多第三方厂商提供的ISAPI过滤器，比如<br>&nbsp;&nbsp;&nbsp; Helicon的ISAPI Rewrite；<br>&nbsp;&nbsp;&nbsp; QwerkSoft的IIS Rewrite；Port80的PageXChanger；<br>&nbsp;&nbsp;&nbsp; 等等。</p>
<p>1.9. 构建网址重写引擎<br>在ASP.NET中实现网址重写很简单，只需调用System.Web.HttpContext类的RewritePath()方法即可。HttpContext类中包含有关于特定HTTP请求的HTTP规范信息。ASP.NET引擎每接收到一个特定请求后便针对该请求创建一个特定的实例，这个类包含一些属性诸如：Request和Response属性，分别提供对请求和响应的访问；Application和Session属性提供对Application变量和Session变量的访问；User属性提供对已授权用户信息的访问。<br>在微软.NET Framework 1.0版本中，RewritePath()方法接收一个新路径的简单字符串，在其内部HttpContext类的RewritePath(string)方法内在地更新Request对象的路径和查询参数。除了RewritePath(string)方法之外，.NET Framework 1.1版还提供了另外一些重载版本，其中一个重载版本接收三个输入字符串参数，这种交替的重载形式不仅仅只是设置Request对象的路径和查询参数这些属性，而是设置更深层的成员变量，这些成员变量用于为PhysicalPath、PathInfo、FilePath属性计算Request对象值。<br>为了实现ASP.NET中的网址重写，我们需要创建一个HttpHandler和HttpModule用于：<br>? 根据请求的路径决定所需要重写的路径；<br>? 重写路径，如果需要的话可以调用RewritePath方法；<br>以前文所构建的那个站点为例，可以通过/info/employee.aspx?empID=EmployeeID来访问每一个雇员的信息。为了使这个网址更加地具有&#8220;隐蔽性&#8221;，我们可能会使用更加容易理解的访问方式如：/people/雇员名.aspx。这里就有了一个网址重写的案例：当接收到对/people/ScottMitchell.aspx的请求的时候，我们就得使用网址重写使得对该页面的请求被重写指向到先前使用的/info/employee?EmpID=1001地址。</p>
<p>1.10. 使用HttpModule来调用网址重写<br>在ASP.NET一级来执行网址重写，既可以使用HttpHandler，也可以使用HttpModule。当使用HttpModule的时候，必须决定如果该网址需要被重写的话，究竟应该在整个请求的生命周期期间的那一个点来使用。乍一看着有些武断，但是这个决定以重大而且微妙的方式影响到你的应用程序。之所以作出对网址重写点的选择是因为内嵌的ASP.NET HttpModule使用Request对象的属性值来完成自己的工作（回忆一下重写路径对Request对象的属性值的改变），这些内嵌HttpModule和相应事件的密切关系列举如下：</p>
<p>HttpModule 事件 简介 <br>FormsAuthenticationModule AuthenticateRequest 判断用户是否已通过表单授权方式获取授权，如果没有的话则将用户重定向到指定的登录页面 <br>FileAuthorizationModule AuthorizeRequest 当使用Windows授权方式的时候，该HttpModule判断并确定该Microsoft Windows帐户是否对其请求的资源拥有足够的权限 <br>UrlAuthorizationModule AuthorizeRequest 检查并确认请求者是否对所访问的网址拥有权限。该Url授权可以在web.config文件的&lt;authorization&gt;和&lt;location&gt;元素中配置 </p>
<p>回想一下BeginRequest事件在AuthenticateRequest事件之前引发，而AuthenticateRequest事件又在AuthorizeRequest事件之前引发。<br>实现网址重写的一个较为安全的场合就是把它放在在BeginRequest事件中执行，这意味着如果要执行网址重写的话，在众多内嵌HttpModule运行的时候他已经完成了。这种途径的最终用途淋漓尽致地体现在表单验证上。当用户访问受限资源的时候，如果之前使用了表单验证，他会自动被重定向到指定的登录页面，在成功登录之后，用户被重定向回先前试图访问的受限制页面。<br>如果把网址重写放在BeginRequest事件或者AuthenticateRequest事件中，在登录页面上执行提交后，该页面会将用户重定向到网址重写指定的页面。假定当用户在浏览器上敲入/people/ScottMitchell.aspx地址，该地址是要被重定向到/info/employee.aspx?EmpID=1001的，如果该Web应用程序设定使用表单验证，当用户开始访问/people/ScottMitchell.aspx的时候，该网址将重写指向/info/employee.aspx?EmpID=1001，接着ForumAuthenticationModule启动，如果需要的话将用户重定向到登录页面，用户登录后重定向到的页面将是/info/employee.aspx?EmpID=1001，这也是自从FormAuthenticationModule启动运行时所发出请求的页面。<br>同上类似，当把网址重写放在BeginRequest事件或者AuthenticateRequest事件中运行的时候，UrlAuthenticationModule也发现了网址重写指向的网址，这意味着如果在该应用程序的web.config文件中&lt;location&gt;节为特定的网址配置特定的授权地址的话，你得引用重写所指向的网址。<br>为了解决这个微妙的问题，一个可能就是把网址重写放在AuthorizeRequest事件中运行，但是在使用这种方法解决URL授权和表单授权的异常时又引入了一个新的缺陷：文件授权会失效。当使用Windows验证的时候，FileAuthorizationModule检查并验证已通过验证的用户是否拥有足够的权限访问特定的ASP.NET页面。<br>假定有一群用户并没有Windows级别的访问权限访问C:\inetpub\wwwroot\info\employee.aspx，当这些用户试图访问/info/employee.aspx?EmpID=1001的时候，他们会得到未授权的错误，如果我们把网址重写放到AuthenticateRequest事件中运行，当FileAuthorizationModule验证该安全性设置的时候，他仍任人为被请求的文件是/people/ScottMitchell.aspx，而这时该网址已经被重写了，因此FileAuthorizationModule会直接放行，让用户看到了网址重写指向的内容：/info/employee.aspx?Empid=1001。<br>那么什么时候在HttpModule调用网址重写合适呢？他决定于所使用的验证方式，当然如果不使用验证方式的话，那么无论是在BeginRequest事件、AuthenticateRequest事件还是AuthorizeRequest事件中调用网址重写没有多大区别，如果使用表单验证方式并且不使用Windows验证方式的话，把网址重写放入AuthorizeRequest事件委托中调用既可，如果使用Windows验证方式的话，把这项功能放入BeginRequest事件或者AuthenticateRequest事件调用就行了。</p>
<p>1.11. 使用HttpHandler来调用网址重写<br>除了上面所述方法外，网址重写也可以放入HttpHandler或者HttpHandlerFactory中调用。HttpHandler是一个负责针对特定请求生成相应内容的类，而HttpHandlerFactory返回一个HTTP的实例，该实例针对特定请求生成相应内容。<br>本节将着眼于为这些ASP.NET页面创建一个网址重写的HttpHandlerFactory。创建HttpHandlerFactory必须实现IHTTPHandlerFactory接口，它包括一个GetHandler()方法。ASP.NET引擎在初始化这些HttpModule后做出决定针对该请求调用相应的HttpHandler或者HttpHandlerFactory，在调用HttpHandlerFactory的时候，针对该Web请求以及随同的其他信息的HttpContext中经过的的HttpHandlerFactory的GetHandler()方法将被ASP.NET引擎调用，HttpHandlerFactory必须返回一个能委托该请求的对象，并且该对象要能实现IHttpHandler接口。<br>要通过一个HttpHandler来调用网址重写，可以先创建一个HttpHandlerFactory，它的GetHandler()方法检查所请求的网址并决定是否需要调用网址重写。如果要调用网址重写的话则调用前文所述的已通过检查的HttpContext对象的RewritePath()方法。最后该HttpHandlerFactory返回一个由类System.Web.UI.PageParser的GetCompiledInstance()方法返回的HttpHandler。（这与内嵌于ASP.NET页面的HttpHandlerFactory（PageHandlerFactory）的工作原理相同。）<br>在所有HttpModule被初始化后，HttpHandlerFactory就开始被实例化。把网址重写放在这些事件场所的最后一个里头调用的时候，也会碰到相同的问题：文件授权将会失效。如果非要依赖于Windows验证和文件验证的时候，你可能得使用HttpModule来调用网址重写了。<br>下一章我们着眼于如何构建一个可重用的网址重写引擎，使用下文所提的这些示例均以真实案例作为参照，在作者主页上提供下载。先用用一个简单的网址重写的例子来探讨如何实现网址重写，紧接着将利用网址重写引擎中正则表达式的强大处理能力来展示真正&#8220;隐蔽&#8221;的网址重写技术！</p>
<p>1.12. 使用网址重写引擎实现简单的网址重写<br>为了便于在Web应用程序中实现网址重写，我构建了一个网址重写引擎，该引擎提供下列功能：<br>? 可以在web.config文件中为页面开发者定义其所使用的网址重写引擎的规则；<br>? 通过使用正则表达式来使所制定的网址重写规则具有更加强大的重写能力；<br>? 能够通过简单配置即可在HttpModule和HttpHandler中使用网址重写。<br>本节只探讨通过HttpModule来实现网址重写，要了解如何通过HttpHandler来实现网址重写请下载本文提供的代码。</p>
<p>1.12.1. 设置网址重写引擎的配置信息<br>我们来探讨一下在web.config中网址重写规则的配置节。首先必须在web.config文件中指出是否需要在HttpHandler或者HttpModule中调用网址重写，在web.config中，下文已经包含了两个已经被注释掉的配置节：</p>
<p>&lt;!--<br>&lt;HttpModules&gt;<br>&nbsp;&nbsp;&nbsp; &lt;add type="URLRewriter.ModuleRewriter,URLRewriter" name="ModuleRewriter"/&gt;<br>&lt;/HttpModules&gt;<br>--&gt;</p>
<p>&lt;!--<br>&lt;httpHandlers&gt;<br>&nbsp;&lt;add verb="*" path="*.aspx" type="URLRewriter.RewriterFactoryHandler,URLRewriter" /&gt;<br>&lt;/httpHandlers&gt;<br>--&gt;</p>
<p>被注释掉的&lt;HttpModules&gt;为配置使用HttpModule调用网址重写；注释掉的&lt;httpHandler&gt;为配置使用HttpHandler调用网址重写。<br>不论配置使用&lt;HttpModules&gt;还是&lt;httpHandlers&gt;调用网址重写，除此之外还须配置网址重写规则，一条重写规则包括两项字符串：请求URL中的查找模式和针对该模式的匹配成功后的替换字符串。该信息在web.config文件中用下列标签描述：</p>
<p>&lt;RewriterConfig&gt;<br>&nbsp;&nbsp;&nbsp; &lt;Rules&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;RewriterRule&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;LookFor&gt;pattern to look for&lt;/LookFor&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;SendTo&gt;String to replace pattern with &lt;/SendTo&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/RewriterRule&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;RewriterRule&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;LookFor&gt;pattern to look for&lt;/LookFor&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;SendTo&gt;String to replace pattern with &lt;/SendTo&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/RewriterRule&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; &lt;/Rules&gt;<br>&lt;/RewriterConfig&gt;</p>
<p>每一条规则都用一个&lt;RewriterRule&gt;元素表示，以&lt;LookFor&gt;节表示查询模式，当查询模式发现匹配字符串时便用&lt;SendTo&gt;节表示的字符串进行替换。这些规则从上到下进行查询匹配，如果找到一个匹配则按此规则执行网址重写，并且停止查找。<br>配置&lt;LookFor&gt;节要使用正则表达式来进行字符串匹配和替换。（在此我们举一个例子来说明如何使用正则表达式来对字符串进行匹配和替换。）既然该查找模式是一个正则表达式，那么要注意避开对正则表达式保留字符串的直接使用。（正则表达式的保留字符串包括有：.，?，^，$，等等，可以通过在前面加上一个反斜线来引用这些保留字符，例如\.表示引用一个句点）</p>
<p>1.12.2. 使用HttpModule来执行网址重写</p>
<p>创建一个HttpModule很简单，只要创建一个实现IHttpModule接口的类，该IHttpModule接口定义了两个方法：<br>? Init(HttpApplication)，该方法在HttpModule初始化时引发，通过该方法为HttpApplication事件调用相应的事件委托；<br>? Dispose()，当相应请求处理结束并发送回IIS调用此方法，通过此方法执行最终所有的清理和回收程序。<br>为了更加方便地为网址重写创建HttpModule，从一开始我就创建一个抽象的基类（BaseModuleRewriter），该类实现了IHttpModule接口。在Init(HttpApplication)事件中，它通过BaseModuleRewriter_AuthorizeRequest方法引发了HttpApplication的AuthorizeRequest事件，该BaseModuleRewriter_AuthorizeRequest方法通过该类的Rewrite()方法重写传入参数HttpApplication对象的内部请求虚拟路径（Path）。在BaseModuleRewriter对象中，该Rewrite()方法是抽象的，并且没有实际内容，但在继承自该类的对象中必须重载Rewrite()方法并为该方法提供实际内容。<br>通过对该基类的继承，所有需要做的工作就是创建一个继承自BaseModuleRewriter的类，重载Rewrite()方法并在该方法中添加网址重写逻辑代码。下文列出BaseModuleRewriter代码：</p>
<p>public abstract class BaseModuleRewriter : IHttpModule<br>{<br>&nbsp;&nbsp;&nbsp; public virtual void Init(HttpApplication app){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // WARNING!&nbsp; This does not work with Windows authentication!<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // If you are using Windows authentication, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // change to app.BeginRequest<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; app.AuthorizeRequest += new EventHandler(this.BaseModuleRewriter_AuthorizeRequest);<br>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public virtual void Dispose() {}</p>
<p>&nbsp;&nbsp;&nbsp; protected virtual void BaseModuleRewriter_AuthorizeRequest(object sender, EventArgs e){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HttpApplication app = (HttpApplication) sender;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Rewrite(app.Request.Path, app);<br>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; protected abstract void Rewrite(string requestedPath, HttpApplication app);<br>}<br>注意：该BaseModuleRewriter类将网址重写放在AuthorizeRequest事件中调用，如果要使用Windows验证并使用文件验证模式时请修改代码将网址授权放在BeginRequest或者AuthenticateRequest事件中。<br>ModuleRewriter继承自BaseModuleRewriter，并真正意义地实现了网址重写的操作，该类仅包含一个重载了的方法Rewrite()，其内容如下文所示：</p>
<p>protected override void Rewrite(string requestedPath, System.Web.HttpApplication app)<br>{<br>&nbsp;&nbsp;&nbsp; // get the configuration rules<br>&nbsp;&nbsp;&nbsp; RewriterRuleCollection rules = RewriterConfiguration.GetConfig().Rules;<br>&nbsp;&nbsp;&nbsp; // iterate through each rule<br>&nbsp;&nbsp;&nbsp; for(int i = 0; i &lt; rules.Count; i++)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // get the pattern to look for, and <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Resolve the Url (convert ~ into the appropriate directory)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string lookFor = "^" + <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, rules[i].LookFor) + "$";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Create a regex (note that IgnoreCase is set)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Regex re = new Regex(lookFor, RegexOptions.IgnoreCase);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // See if a match is found<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (re.IsMatch(requestedPath))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // match found - do any replacement needed<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string sendToUrl = RewriterUtils.ResolveUrl(app.Context.Request.ApplicationPath, re.Replace(requestedPath, rules[i].SendTo));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Rewrite the URL<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RewriterUtils.RewriteUrl(app.Context, sendToUrl);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // exit the for loop<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>}</p>
<p>该Rewriter()方法以获取web.config文件中的网址重写规则的设置为起始，它通过循环访问各条网址重写规则，每次均获取当前规则中的LookFor属性，用正则表达式验证并判断是否查找是否对当前请求的网址是否有匹配。<br>如果发现一条匹配，将用当前规则的SendTo值对请求的路径执行一个正则表达式替换，替换后的地址通过参数的形式传给RewriterUtils.RewriteUrl()方法，RewriterUtils是一个帮助类，它提供一对HttpModule和HttpHandler都可以使用的静态方法，RewriterUrl()方法只是简单地调用了HttpContext对象的RewritePath()方法。<br>注意：你已经注意到了当执行正则表达式匹配和替换的时候调用了一个RewriterUtils.ResolveUrl()方法。该帮助方法简单地替换了应用程序路径中&#8220;~&#8221;的所有实例。<br>本文附录中提供所有涉及该网址重写引擎的代码下载，我们已经探讨了主要的部分，但是还有其它一些组件诸如将web.config文件中XML格式化了的网址重写规则反序列化至一个对象的类定义、通过HttpHandlerFactory实现网址重写的类定义等。本文最后三节将通过一些真实案例来探讨网址重写的技术。</p>
<p>1.12.3. 用网址重写引擎实现简单的网址重写<br>为了更好地示范网址重写引擎的运行，我们来建立一个ASP.NET Web应用程序来实现简单的网址重写引擎。假定我们为一家在线销售各类商品的公司服务，这些产品划分为以下类别：<br>分类编号(CategoryID) 分类名称(CategoryName)<br>1 饮料（Beverages）<br>2 调味品（Condiments）<br>3 工艺品（Confections）<br>4 日记本（Diary Products）<br>... ...<br>假定已经建立好一个名为ListProductsByCategoryID.aspx的ASP.NET页面文件，它通过查询参数获取一个分类编号，并根据此编号获取所有该分类下的所有商品。如果用户想浏览所销售的饮料类商品可以通过ListProductsByCategoryID.aspx?CategoryID=1来访问，如果用户想浏览所销售的日记本类商品可以通过ListProductsByCategoryID.aspx?CategoryID=4来访问。假定还有一个页面ListCategories.aspx，它列出所有代售商品的分类编号。<br>显然这里发现了一个网址重写的案例。对于用户来说他们所输入的地址不具有任何实际意义并且不具备任何&#8220;隐蔽性&#8221;，倒不如使用网址重写引擎让用户去访问/Products/Baverage.aspx地址，系统将该地址重写到ListProductsByCategoryID.aspx?CategoryID=1。我们可以在web.config文件中来完成网址重写任务：</p>
<p>&lt;RewriterConfig&gt;<br>&nbsp;&nbsp;&nbsp; &lt;Rules&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!—- Rules for products lister --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;RewriterRule&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;LookFor&gt;~/Products/Baverage.aspx&lt;/LookFor&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;SendTo&gt;~/ListProductsByCategoryID.aspx?CategoryID=1&lt;/SendTo&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/RewriterRule&gt;<br>&nbsp;&nbsp;&nbsp; &lt;/Rules&gt;<br>&lt;/RewriterConfig&gt;<br>很明显地看到，搜索用户访问的路径是否匹配/Products/Baverage.aspx，如果匹配的话，则将网址重写到/ListProductsByCategoryID.aspx?CategoryID=1。<br>注意：你会发现&lt;LookFor&gt;节点中避免直接在&#8220;Baverage.aspx&#8221;中使用句点&#8220;.&#8221;是因为&lt;LookFor&gt;节点的值是正则表达式的匹配模式，在正则表达式中句点符号是一个特殊字符，它表示匹配任何一个字符，也就是说如果访问BaverageQaspx时也会发生匹配，为了避免发生这个句点引起的匹配我们得在该句点符号前面加上一个&#8220;\&#8221;，表示引用句点符号<br>通过该规则定义，当用户访问/Products/Baverage.aspx文件的时候，他们将看到代售的饮料类商品列表信息。图3为访问/Products/Baverage.aspx地址时的浏览器截图，注意在浏览器中地址栏上显示的是用户输入的/Products/Baverage.aspx地址，但是实际访问的地址却是网址重写后的/ListProductsByCategoryID.aspx?CategoryID=1。（事实上，在服务器上根本就不存在/Products/Baverage.aspx文件！）</p>
<p><br>图三．网址重写后的对商品分类的请求</p>
<p>和/Products/Baverage.aspx类似，下一步我们添加其它分类的重写规则，只需简单地在web.config文件中&lt;Rules&gt;中在添加其他&lt;RewriteRule&gt;节即可。该演示完整的重写规则集合请参考下载文档的web.config文件中的定义。<br>为了让该网址更具有&#8220;隐蔽性&#8221;，如果让用户把/Products/Baverage.aspx后面Baverage.aspx一段截去，在浏览器中输入/Products/来浏览产品分类列表会更好一些。乍一看，这项任务微不足道，只需添加一条网址重写规则将/Products/映射到/ListCategories.aspx即可。然而这里有一个微妙之处，你必须先创建一个/Products/目录，并在里面放一个空文件Default.aspx。<br>要认识为什么这些额外的步骤是必须的，先回顾一下前文。网址重写引擎是处于ASP.NET一级的，也就是说，如果ASP.NET没有获得处理请求的机会的话，网址重写引擎就不能对输入的网址请求作出判断。此外，IIS仅在请求文件包含相应扩展名时才将请求转交给ASP.NET引擎。如果用户访问/Products/，IIS并不知道其扩展名是什么，于是它检查该目录下的文件看是否包含有默认首页文件名（Default.aspx,Default.htm,Default.asp,等等，这些文件名在IIS管理工具对话框中Web服务器属性对话框中的文档标签中定义。）当然，如果/Products/目录不存在的话，IIS将返回一个HTTP 404错误。<br>所以我们需要创建一个/Products/目录并在该目录下额外创建一个空文件Default.aspx，IIS会检查该目录下的文件，发现有一个默认文件名Default.aspx，于是将请求转交给ASP.NET，这样，网址重写引擎才能生效。</p>
<p>&lt;RewriterRule&gt;<br>&nbsp;&nbsp;&nbsp; &lt;LookFor&gt;~/Products/Default.aspx&lt;/LookFor&gt;<br>&nbsp;&nbsp;&nbsp; &lt;SendTo&gt;~ListCategories.aspx&lt;/SendTo&gt;<br>&lt;/RewriterRule&gt;<br>通过该规则，用户访问/Products/Default.aspx或者访问/Products/都可以看到如图四所示的产品分类列表。</p>
<p>图四.在网址上添加&#8220;隐蔽性&#8221;</p>
<p><br>1.12.4.处理回送数据<br>如果要重写的网址上包含有服务器端Web Form并执行数据回送，当该Web Form回送数据时会暴露出真实的网址，也就是说，当用户访问/Products/Baverage.aspx时，浏览器上地址栏显示的也是/Products/Baverage.aspx，但是实际上是访问/ListProdutsByCategoryID.aspx?CategoryID=1的内容，如果ListProductsByCategoryID.aspx页面执行了数据回送的话，用户被数据回送定向给原始的/ListProductByCategoryID.aspx?CategoryID=1页面上，而不是/Products/Baverage.aspx页面。这虽然不是什么大问题，但是用户会觉察到点击一个按钮时网址发生了的变化，这也许会令人不安，因为如果出于网址安全的角度来说，直接把真实的网址暴露出来了。<br>之所以发生这种现象的原因是当Web Form在呈现之时就明确地设置其action属性为当前Request对象中文件路径的值。当然，在Web Form呈现之时，从/Produts/Baverage.aspx到/ListProductsByCategoryID.aspx?CategoryID=1的网址重写就已经执行完毕了，这意味着Request对象所汇报的是当前用户所访问的地址是/ListProductsByCategoryID.aspx?CategoryID=1。这么看来，只需让该服务器端表单在呈现之时不呈现action属性即可解决问题了。（对浏览器来说，如果不设置action属性的话，那么在提交的时候将使用其默认值。）<br>然而不幸的是该Web Form不会允许你指定action属性，也不会允许你通过设置一些属性来达到禁用呈现action属性的目的。得自行继承System.Web.HtmlControls.HtmlForm这个类，并重载该类的RenderAttribute()方法，明确指出该类不呈现acton属性。<br>感谢继承这个强大的功能，使得我们很简单就获取了HtmlForm这个类下所有的功能定义，只需少量几行代码就达到所需目的，完整代码如下所示：</p>
<p>namespace ActionlessForm<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public class Form:System.Web.UI.WebControls.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; protected override void RenderAttributes(System.Web.UI.HtmlTextWriter writer)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; writer.WriteAttribute("name",this.Name);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; base.Attributes.Remove("name");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; writer.WriteAttribute("method",this.Method);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; base.Attributes.Remove("method");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Attributes.Render(writer);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; base.Attributes.Remove("action");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (base.ID!=null)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; writer.WriteAttribute("id",this.ClientID);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>}</p>
<p>对RenderAttributes()方法重载的代码包含了原类HtmlForm的RenderAttributes()方法全部的代码内容，只是简单地去掉了设置action属性这一节。（我参考了Lutz Roeder的Reflecter一文中类HtmlForm的源代码）<br>当创建并编译了这个类后，将其添加到引用目录即可在该ASP.NET Web应用程序中使用。为了将原有HtmlForm类替换，只需简单地在页面顶部添加下列代码：</p>
<p>&lt;%@ Register TagPrifix="skm" Namespace="ActionlessForm" Assembly="ActionlessForm"%&gt;<br>然后将&lt;Form runat=&#8221;server&#8221;&gt;标签替换为</p>
<p>&lt;skm:Form id="Form1" method="post" runat="Server"&gt;<br>并将结束标记&lt;/Form&gt;替换为</p>
<p>&lt;skm:Form&gt;<br>你可以查看该文档相关下载中的ListProductsByCategoryID.aspx文件中的自定义Web Form，该下载已经提供了完整的Visual Studio.NET项目文件包。<br>注意：如果你打算进行网址重写的地址不执行数据回送，则没有必要使用该自定义Web Form的类。</p>
<p>1.13. 创建真正&#8220;隐蔽&#8221;的网址<br>上一节简单网址重写的示例展示了如何通过新的网址重写规则来轻松地配置网址重写引擎，本节将通过出众的正则表达式来展示网址重写的强大威力。<br>时下正在流行Blog，很多人都拥有一个自己的Blog。不论你是否对Blog感到陌生，他们正在不断地更新自己的Blog页面，这些页面就像一个个人日记本一样。大多数Bloger只是简单地记录每天发生的事情，也有一些聚焦于某一主题，比如影评、球迷组织、电脑技术等。<br>Blog可以在任何地点由作者进行更新，更新次数可以是一天多次，也可以是一周一两次。在Blog页面上只显示最近10条更新，但事实上所有的Blog软件都提供了存档记录，访客可以阅读其历史记录。有了&#8220;隐蔽&#8221;的网址，Blog应用程序将变得更加强大。假定你通过/2004/02/14.aspx来查询自己的Blog上的文章，你会为阅读到2004年2月14日的Blog感到惊讶吗？此外你可能为了访问2004年2月所有的Blog而将该地址裁减为/2004/02/，要访问2004年所有的Blog，你可能会试着去访问/2004/。<br>在维护一个Blog的时候，如果将这种具有&#8220;隐蔽性&#8221;的网址提供给用户将会更好。实际上很多Blog引擎都提供了这种网址重写的功能，现在来看看这些是如何通过网址重写实现的。<br>首先，我们需要一个页面能够分别按照年、月、日分别显示Blog的内容。假定现在已经做好了一个页面文件ShowBlogContent.aspx，它能分别获取年、月、日的查询参数，要查看2004年2月14日所发的帖子，我们可以访问/ShowBlogContent.aspx?year=2004&amp;month=2&amp;day=14，要浏览2004年2月的数据可以访问/ShowBlogContent.aspx?year=2004&amp;month=2，要查询2004年所有数据可以访问/ShowBlogContent.aspx?year=2004。（在下载文件中提供ShowBlogContent.aspx源代码。）<br>然后，当用户访问/2004/02/14.aspx时，我们需要将他访问的网址重写到/ShowBlogContent.aspx?year=2004&amp;month=2&amp;day=14上。这里需要制定三条网址重写规则：当指定访问年月日时、当指定访问年月时和当指定访问年时。</p>
<p>&lt;RewriterConfig&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Rules&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!-- Rules for Blog Content Displayer --&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;RewriterRule&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;LookFor&gt;~/(d{4})/(d{2})/(d{2}).aspx&lt;/LookFor&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;SendTo&gt;~/ShowBlogContent.aspx?year=$1&amp;amp;month=$2&amp;amp;day=$3&lt;/SendTo&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/RewriterRule&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;RewriterRule&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;LookFor&gt;~/(d{4})/(d{2})/Default.aspx&lt;/LookFor&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;SendTo&gt;&lt;![CDATA[~/ShowBlogContent.aspx?year=$1&amp;month=$2]]&gt;&lt;/SendTo&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/RewriterRule&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;RewriterRule&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;LookFor&gt;~/(d{4})/Default.aspx&lt;/LookFor&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;SendTo&gt;~/ShowBlogContent.aspx?year=$1&lt;/SendTo&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/RewriterRule&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/Rules&gt;<br>&lt;/RewriterConfig&gt;<br>这些网址重写规则展示了正则表达式的强大威力。第一条规则按照(\d{4})/(\d{2})/(\d{2})\.aspx模式进行查找，通俗的说，它查找是否包含匹配xxxx/xx/xx.aspx格式的字符串，其中x表示数字，每一组数字必须用圆括号括起来，这样可以在相应&lt;SendTo&gt;节内引用圆括号内的匹配字符串。我们可以使用$1、$2、$3来分别引用前面匹配的圆括号组，其中$1，$2，$3分别表示所匹配的第一、第二、第三个圆括号组。<br>注意：由于web.config是XML格式的文档，所以在文本域内必须回避直接使用一些特殊字符，如：&amp;，&lt;和&gt;符号等。在第一条网址重写规则的&lt;SendTo&gt;节中用&amp;amp来表示引用&amp;符号，在第二条网址重写规则的&lt;SendTo&gt;节中用&lt;![CDATA[...]]&gt;元素来表示其中所有的内容都是文本域，不再需要用转义字符来表示引用。这两种方法都可以实现同样的目的。<br>下面图五、图六、图七都显示出网址重写的运行状况。这些数据都真实地摘自作者的Blog（<a href="http://scottonwritting.net/">http://ScottOnWritting.net</a>），图五显示2003年11月7日的帖子，图六显示所有2003年11月的帖子，图七显示2003年所有帖子。</p>
<p>图五.显示2003年11月7日的帖子</p>
<p><br>图六. 显示2003年11月所有的帖子</p>
<p><br>图七. 显示2003年所有的帖子</p>
<p><br>注意：要使用网址重写引擎，强烈推荐在&lt;LookFor&gt;节中使用正则表达式。如果你对正则表达式不是很熟悉，可以先阅读作者本人写的一篇文章An Introduction to Regular Expressions，此外还可以在RegexLib.com 上查询常用的正则表达式，或把你自己设计的正则表达式提交到该站点共享使用。</p>
<p>1.14. 创建必须的目录结构<br>当IIS接收到对/2004/03/19.aspx的请求时，他发现文件扩展名.aspx，便将该请求转交给ASP.NET引擎处理，在ASP.NET 引擎中传递时，该地址被重写到/ShowBlogContent.aspx?year=2004&amp;month=3&amp;day=19，最后用户将看到该Blog上2004年3月19日所有的帖子，但是在用户访问/2004/03/时会发生什么呢？除非已经存在一个/2004/01/的目录，否则IIS将返回一个404错误，而且该目录下还必须要有一个默认页面Default.aspx，IIS才能将请求转交给ASP.NET引擎处理。<br>通过这种方法你得手动为每一年的Blog创建一个年份的目录并在该年份下放置一个默认文件Default.aspx，而且还得在该年份目录下创建每一月的目录，从01、02、...、12，每一个目录下也要防止一个默认文件Default.aspx。（回想前面的例子，为了将/Products/重写到/ListCategories.aspx也是要建立一个/Products/目录并放置一个默认Default.aspx文件。<br>很明显，这样创建目录结构的过程是很痛苦的。解决这种问题的一个办法就是设置IIS将所有接收的请求都转交给ASP.NET引擎来处理，这种方法，甚至连访问这种地址/2004/04/，IIS都如实地将其转交给ASP.NET引擎处理，这种方法造成ASP.NET引擎得处理所有传入的请求，包括css文件，图片文件、Javascript文件以及Flash文件等等。<br>关于对所有类型文件的处理的详细讨论已经超出了本书范围。有关在ASP.NET Web应用程序中使用这些技术的例子请访问 .Text 这个开源的Blog。.Text 可以通过配置将所有请求都转交给ASP.NET处理。它使用了一个自定义的HttpHandler来处理所有类型的文件类型，这个自定义的HttpHandler可以识别并判断如何处理所有的文件类型。（图像文件、CSS文件等等。）</p>
<p>1.15. 结束语<br>本文探讨了通过类HttpContext类的RewriteUrl()方法来实现ASP.NET一级的网址重写，正如我们所看到那样，RewriteUrl()方法在修改这个特有的HttpContext的Request的属性时也修改了所请求的文件和路径。实际得到的效果就是在用户访问其特有的网址的时候，他实际却是在服务器端请求另一个与此不同的网址。<br>网址重写不但可以在HttpModule中执行，也可以在HttpHandler中运行。本文我们探讨了在一个HttpModule中执行网址重写，也研究了一下网址重写在ASP.NET中的各个不同场所的情况。<br>当然，在ASP.NET一级的网址重写中，只有在IIS成功地将请求转交给ASP.NET引擎后才能成功地执行，当用户请求一个扩展名为.aspx的文件时这很自然地发生。然而，如果要让用户输入一个实际并不存在的网址，通过网址重写到另一个存在的aspx页面，你必须为该请求创建相应的目录和默认的Default.aspx页面，除非配置IIS让它把所有的请求都转交给IIS处理，但是这种方式盲目地将所有请求都转交给了ASP.NET引擎。</p>
<p>1.16. 参考<br>本文源代码下载地址：<a href="http://download.microsoft.com/download/0/4/6/0463611e-a3f9-490d-a08c-877a83b797cf/MSDNURLRewriting.msi">http://download.microsoft.com/download/0/4/6/0463611e-a3f9-490d-a08c-877a83b797cf/MSDNURLRewriting.msi</a><br>《深入研究IIS与ASP.NET》(Inside IIS and ASP.NET) 作者：Michele Leroux Bustamante<br>工作参考：网址重写是一个颇受欢迎的主题，不论是ASP.NET还是其他竞争对手都对其表示出巨大的关注。例如：Apache Web Server提供了一个叫做mod_rewriting的模块，mod_rewriting是个功能完善的网址重写引擎，它提供基于HTTP 头信息和服务器参数环境的网址重写功能，甚至还提供用正则表达式来创建网址重写规则。有关mod_rewriting更多信息请参考A User's Guide to URL Rewriting with the Apache Web Server《Apache Web Server网址重写用户向导》。<br>这里有相当数量的关于ASP.NET级别下网址重写的文章：<br>Rewrite.NET - A URL Rewriting Engine for .NET探讨模拟mod_rewriting的正则表达式描述的网址重写规则来实现ASP.NET下网址重写；<br>URL Rewriting With ASP.NET提供对ASP.NET下网址重写能力的总的概述；<br>Ian Griffiths有一个Blog，上面有许多有关在ASP.NET中实现网址重写的建议，比如本文所提到的考虑到数据回送时的做法；<br>Fabrice Marguerie和Jason Salas都各有一个Blog，在上面可以找到有关将ASP.NET网址重写来推动搜索引擎的查找替换的文章。<br>（Fabrice Marguerie: <a href="http://weblogs.asp.net/fmarguerie/archive/2003/12/24/45712.aspx">http://weblogs.asp.net/fmarguerie/archive/2003/12/24/45712.aspx</a>）<br>（Jason Salas: <a href="http://weblogs.asp.net/jasonsalas/archive/2003/12/14/43404.aspx">http://weblogs.asp.net/jasonsalas/archive/2003/12/14/43404.aspx</a>）</p>
<p><br>本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/kanshangren/articles/67505.aspx">http://blog.csdn.net/kanshangren/articles/67505.aspx</a></p>
<img src ="http://www.cnitblog.com/afa202/aggbug/60763.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/afa202/" target="_blank">火炏炎焱燚</a> 2009-08-12 17:04 <a href="http://www.cnitblog.com/afa202/archive/2009/08/12/60763.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java乱码</title><link>http://www.cnitblog.com/afa202/archive/2009/07/20/60222.html</link><dc:creator>火炏炎焱燚</dc:creator><author>火炏炎焱燚</author><pubDate>Mon, 20 Jul 2009 02:57:00 GMT</pubDate><guid>http://www.cnitblog.com/afa202/archive/2009/07/20/60222.html</guid><wfw:comment>http://www.cnitblog.com/afa202/comments/60222.html</wfw:comment><comments>http://www.cnitblog.com/afa202/archive/2009/07/20/60222.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/afa202/comments/commentRss/60222.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/afa202/services/trackbacks/60222.html</trackback:ping><description><![CDATA[<p>1，最基本的乱码问题。<br>这个乱码问题是最简单的乱码问题。一般新会出现。就是页面编码不一致导致的乱码。<br>&lt;%@ page language="java" pageEncoding="UTF-8"%&gt;<br>&lt;%@ page contentType="text/html;charset=iso8859-1"%&gt;<br>&lt;html&gt;<br>&lt;head&gt;<br>&lt;title&gt;中文问题&lt;/title&gt;<br>&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&gt;<br>&lt;/head&gt;<br>&lt;/head&gt;<br>&lt;body&gt;<br>我是个好人<br>&lt;/body&gt;<br>&lt;/html&gt;<br>三个地方的编码。<br>第一个地方的编码格式为jsp文件的存储格式。Ecljpse会根据这个编码格式保存文件。并编译jsp文件，包括里面的汉字。<br>第 二处编码为解码格式。因为存为UTF-8的文件被解码为iso8859-1，这样 如有中文肯定出乱码。也就是必须一致。而第二处所在的这一行，可以没有。缺省也是使用iso8859-1的编码格式。所以如果没有这一行的话，&#8220;我是个好 人&#8221;也会出现乱码。必须一致才可以。<br>第三处编码为控制浏览器的解码方式。如果前面的解码都一致并且无误的话，这个编码格式没有关系。有的网页出现乱码，就是因为浏览器不能确定使用哪种编码格式。因为页面有时候会嵌入页面，导致浏览器混淆了编码格式。出现了乱码。</p>
<p>&#160;</p>
<p>2， 表单使用Post方式提交后接收到的乱码问题<br>这 个问题也是一个常见的问题。这个乱码也是tomcat的内部编码格式iso8859-1在捣乱，也就是说post提交时，如果没有设置提交的编码格式，则 会以iso8859-1方式进行提交，接受的jsp却以utf-8的方式接受。导致乱码。既然这样的原因，下面有几种解决方式，并比较。<br>A，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 接受参数时进行编码转换<br>String str = new String(request.getParameter("something").getBytes("ISO-8859-1"),"utf-8") ； 这样的话，每一个参数都必须这样进行转码。很麻烦。但确实可以拿到汉字。<br>B，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在请求页面上开始处，执行请求的编码代码， request.setCharacterEncoding("UTF-8")，把提交内容的字符集设为UTF－8。这样的话，接受此参数的页面就不必在转码了。直接使用<br>String str = request.getParameter("something")；即可得到汉字参数。但每页都需要执行这句话。这个方法也就对post提交的有效 果，对于get提交和上传文件时的enctype="multipart/form-data"是无效的。稍后下面单独对这个两个的乱码情况再进行说明。<br>C， 为了避免每页都要写request.setCharacterEncoding("UTF-8")，建议使用过滤器对所有jsp<br>进行编码处理。这个网上有很多例子。请大家自己查阅。</p>
<p>/***********************************************************过滤器的使用*******************************************************/<br>现在将常见的乱码问题分为JSP页面显示中文乱码、表单提交乱码两类。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 1）JSP页面中显示中文乱码</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 在JSP文件中使用page命令指定响应结果的MIME类型，如&lt;%@ page language="java" contentType="text/html;charset=gb2312" %&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 2）表单提交乱码&nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 表单提交时（post和Get方法），使用request.getParameter方法得到乱码，这是因为tomcat处理提交的参数时默认的是iso-8859-1，表单提交get和post处理乱码问题不同，下面分别说明。<br>&nbsp;&nbsp;&nbsp; (1)POST处理<br>&nbsp;&nbsp;&nbsp; 对post提交的表单通过编写一个过滤器的方法来解决，过滤器在用户提交的数据被处理之前被调用，可以在这里改变参数的编码方式，过滤器的代码如下：</p>
<p>Java代码 <br>CharacterEncodingFilter.java:</p>
<p>public class CharacterEncodingFilter implements Filter <br>{</p>
<p>protected String encoding = null;</p>
<p>public void init(FilterConfig filterConfig) throws ServletException <br>{<br>this.encoding = filterConfig.getInitParameter("encoding");<br>}</p>
<p>public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException <br>{<br>request.setCharacterEncoding(encoding);<br>response.setContentType("text/html;charset="+encoding);<br>chain.doFilter(request, response);<br>}</p>
<p>}</p>
<p>web.xml:</p>
<p>&lt;filter&gt;<br>&lt;filter-name&gt;CharacterEncodingFilter&lt;/filter-name&gt;<br>&lt;filter-class&gt;net.vschool.web.CharacterEncodingFilter&lt;/filter-class&gt;<br>&lt;init-param&gt;<br>&lt;param-name&gt;encoding&lt;/param-name&gt;<br>&lt;param-value&gt;GBK&lt;/param-value&gt;<br>&lt;/init-param&gt;<br>&lt;/filter&gt;<br>&lt;filter-mapping&gt;<br>&lt;filter-name&gt;CharacterEncodingFilter&lt;/filter-name&gt;<br>&lt;url-pattern&gt;/*&lt;/url-pattern&gt;<br>&lt;/filter-mapping&gt;</p>
<p><br>(2) Get方法的处理<br>tomcat对post和get的处理方法不一样，所以过滤器不能解决get的乱码问题，它需要在其他地方设置。<br>打开&lt;tomcat_home&gt;\conf目录下server.xml文件，找到对8080端口进行服务的Connector组件的设置部分，给这个组件添加一个属性：URIEncoding="GBK"。修改后的Connector设置为：<br></p>
<p>Java代码 <br>&lt;Connector port="8080" maxHttpHeaderSize="8192" <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxThreads="150" minSpareThreads="25" maxSpareThreads="75" <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enableLookups="false" redirectPort="8443" acceptCount="100" <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connectionTimeout="20000" disableUploadTimeout="true" &lt;SPAN style="COLOR: #ff0000"&gt;URIEncoding="GBK"&lt;/SPAN&gt; /&gt; </p>
<p>&lt;Connector port="8080" maxHttpHeaderSize="8192"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxThreads="150" minSpareThreads="25" maxSpareThreads="75"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enableLookups="false" redirectPort="8443" acceptCount="100"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="GBK" /&gt;<br>* 注意修改后重新启动tomcat才能起作用。</p>
<p>/***********************************************************过滤器的使用*******************************************************/</p>
<p><br>3，表单get提交方式的乱码处理方式。<br>如果使用get方式提交中文，接受参数的页面也会出现乱码，这个乱码的原因也是tomcat的内部编码格式iso8859-1导致。Tomcat会以get的缺省编码方式iso8859-1对汉字进行编码，编码后追加到url，导致接受页面得到的参数为乱码/、。<br>解决办法：<br>A，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用上例中的第一种方式，对接受到的字符进行解码，再转码。<br>B，&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Get走的是url提交，而在进入url之前已经进行了iso8859-1的编码处理。要想影响这个编码则需要在server.xml的Connector节点增加useBodyEncodingForURI="true" <br>属 性配置，即可控制tomcat对get方式的汉字编码方式，上面这个属性控制get提交也是用 request.setCharacterEncoding("UTF-8")所设置的编码格式进行编码。所以自动编码为utf-8，接受页面正常接受就 可以了。</p>
<p>但我认为真正的编码过程是，tomcat又要根据<br>&lt;Connector port="8080" <br>maxThreads="150" minSpareThreads="25" maxSpareThreads="75" <br>enableLookups="false" redirectPort="8443" acceptCount="100" <br>debug="0" connectionTimeout="20000" useBodyEncodingForURI="true" <br>disableUploadTimeout="true" URIEncoding=&#8221;UTF-8&#8221;/&gt;<br>里面所设置的URIEncoding=&#8221;UTF-8&#8221;再进行一次编码，但是由于已经编码为utf-8，再编码也不会有变化了。如果是从url获取编码，接受页面则是根据URIEncoding=&#8221;UTF-8&#8221;来进行解码的。</p>
<p><br>4， 上传文件时的乱码解决<br>上传文件时，form表单设置的都是enctype="multipart/form-data"。这种方式以流方式提交文件。如果使用apach的上传 组件，会发现有很多乱码想象。这是因为apach的先期commons-fileupload.jar有bug，取出汉字后进行解码，因为这种方式提交， 编码又自动使用的是tomcat缺省编码格式iso-8859-1。但出现的乱码问题是： 句号，逗号，等特殊符号变成了乱码，汉字如果数量为奇数，则会出现乱码，偶数则解析正常。<br>&nbsp;&nbsp;&nbsp; 解决方式： 下载commons-fileupload-1.1.1.jar 这个版本的jar已经解决了这些bug。<br>但是取出内容时仍然需要对取出的字符进行从iso8859-1到utf-8转码。已经能得到正常所有汉字以及字符。</p>
<p><br>5，Java代码关于url请求，接受参数的乱码<br>url的编码格式，取决于上面所说的URIEncoding=&#8221;UTF-8&#8221;。 如果设定了这个编码格式，则意味着所有到url的汉字参数，都必须进行编码才可以。否则得到的汉字参数值都是乱码，例如<br>一个链接 Response.sendDerect（&#8220;/a.jsp?name=张大维&#8221;）；而在a.jsp里面直接使用<br>String name = request.getParameter（"name"）；得到的就是乱码。因为规定了必须是utf-8才可以，所以，这个转向应该这样写： <br>&nbsp;&nbsp;&nbsp; Response.sendDerect（&#8220;/a.jsp?name=URLEncode.encode(&#8220;张大维&#8221;,&#8221;utf-8&#8221;)；才可以。<br>如 果不设置这个参数URIEncoding=&#8221;UTF-8&#8221;， 会怎么样呢? 不设置则就使用了缺省的编码格式iso8859-1。问题又出来了，第一就是参数值的个数如果是奇数个数，则就可以正常解析，如果使偶数个数，得到最后字 符就是乱码。还有就是如果最后一个字符如果是英文，则就能正常解析，但中文的标点符号仍出现乱码。权宜之计，如果您的参数中没有中文标点符号，则可以在参 数值最后加一个英文符号来解决乱码问题，得到参数后再去掉这个最后面的符号。也可以凑或使用。</p>
<p><br>6， 脚本代码关于url请求，接受到的参数乱码<br>脚 本中也会进行页面转向的控制，也会涉及到附带参数，并在接受页面解析这个参数的情况。如果这个汉字参数不进行URIEncoding=&#8221;UTF-8&#8221;所指 定的编码处理，则接受页面接受到的汉字也是乱码。脚本处理编码比较麻烦，必须有相应的编码脚本对应文件，然后调用脚本中的方法对汉字进行编码即可。</p>
<p><br>7， 关于jsp在MyEclipse中打开的乱码问题<br>对 于一个已经存在的项目，Jsp文件的存储格式可能是utf-8。如果新安装的eclipse，则缺省打开使用的编码格式都是iso8859-1。所以导致 jsp里面的汉字出现乱码。这个乱码比较容易解决，直接到eclipse3.1的偏好设置里面找到general-〉edidor，设置为您的文件打开编 码为utf-8即可。Eclipse会自动重新以新的编码格式打开。汉字即可正常显示。</p>
<p><br>8， 关于html页面在eclipse中打开出现乱码情况<br>由于大部分页面都是由dreamweaver制作，其存储格式跟eclipse的识别有差别导致。<br>一般这种情况，在eclipse中新建一个jsp，直接从dreamweaver复制页面内容粘贴到jsp即可</p>
<p>但我认为真正的编码过程是，tomcat又要根据<br>&lt;Connector port="8080" <br>maxThreads="150" minSpareThreads="25" maxSpareThreads="75" <br>enableLookups="false" redirectPort="8443" acceptCount="100" <br>debug="0" connectionTimeout="20000" useBodyEncodingForURI="true" <br>disableUploadTimeout="true" URIEncoding=&#8221;UTF-8&#8221;/&gt;<br>里面所设置的URIEncoding=&#8221;UTF-8&#8221;再进行一次编码，但是由于已经编码为utf-8，再编码也不会有变化了。如果是从url获取编码，接受页面则是根据URIEncoding=&#8221;UTF-8&#8221;来进行解码的。</p>
<p><br>4， 上传文件时的乱码解决<br>上传文件时，form表单设置的都是enctype="multipart/form-data"。这种方式以流方式提交文件。如果使用apach的上传 组件，会发现有很多乱码想象。这是因为apach的先期commons-fileupload.jar有bug，取出汉字后进行解码，因为这种方式提交， 编码又自动使用的是tomcat缺省编码格式iso-8859-1。但出现的乱码问题是： 句号，逗号，等特殊符号变成了乱码，汉字如果数量为奇数，则会出现乱码，偶数则解析正常。<br>&nbsp;&nbsp;&nbsp; 解决方式： 下载commons-fileupload-1.1.1.jar 这个版本的jar已经解决了这些bug。<br>但是取出内容时仍然需要对取出的字符进行从iso8859-1到utf-8转码。已经能得到正常所有汉字以及字符。</p>
<p><br>5，Java代码关于url请求，接受参数的乱码<br>url的编码格式，取决于上面所说的URIEncoding=&#8221;UTF-8&#8221;。 如果设定了这个编码格式，则意味着所有到url的汉字参数，都必须进行编码才可以。否则得到的汉字参数值都是乱码，例如<br>一个链接 Response.sendDerect（&#8220;/a.jsp?name=张大维&#8221;）；而在a.jsp里面直接使用<br>String name = request.getParameter（"name"）；得到的就是乱码。因为规定了必须是utf-8才可以，所以，这个转向应该这样写： <br>&nbsp;&nbsp;&nbsp; Response.sendDerect（&#8220;/a.jsp?name=URLEncode.encode(&#8220;张大维&#8221;,&#8221;utf-8&#8221;)；才可以。<br>如 果不设置这个参数URIEncoding=&#8221;UTF-8&#8221;， 会怎么样呢? 不设置则就使用了缺省的编码格式iso8859-1。问题又出来了，第一就是参数值的个数如果是奇数个数，则就可以正常解析，如果使偶数个数，得到最后字 符就是乱码。还有就是如果最后一个字符如果是英文，则就能正常解析，但中文的标点符号仍出现乱码。权宜之计，如果您的参数中没有中文标点符号，则可以在参 数值最后加一个英文符号来解决乱码问题，得到参数后再去掉这个最后面的符号。也可以凑或使用。</p>
<p><br>6， 脚本代码关于url请求，接受到的参数乱码<br>脚 本中也会进行页面转向的控制，也会涉及到附带参数，并在接受页面解析这个参数的情况。如果这个汉字参数不进行URIEncoding=&#8221;UTF-8&#8221;所指 定的编码处理，则接受页面接受到的汉字也是乱码。脚本处理编码比较麻烦，必须有相应的编码脚本对应文件，然后调用脚本中的方法对汉字进行编码即可。</p>
<p><br>7， 关于jsp在MyEclipse中打开的乱码问题<br>对 于一个已经存在的项目，Jsp文件的存储格式可能是utf-8。如果新安装的eclipse，则缺省打开使用的编码格式都是iso8859-1。所以导致 jsp里面的汉字出现乱码。这个乱码比较容易解决，直接到eclipse3.1的偏好设置里面找到general-〉edidor，设置为您的文件打开编 码为utf-8即可。Eclipse会自动重新以新的编码格式打开。汉字即可正常显示。</p>
<p><br>8， 关于html页面在eclipse中打开出现乱码情况<br>由于大部分页面都是由dreamweaver制作，其存储格式跟eclipse的识别有差别导致。<br>一般这种情况，在eclipse中新建一个jsp，直接从dreamweaver复制页面内容粘贴到jsp即可</p>
<p>&#160;</p>
<p><br>2008-02-11 11:54<br>　　在使用JSP的过程中，最使人头疼的一个问题就是中文乱码问题，以下是我在软件开发中遇到的乱码问题以及解决方法。</p>
<p>1、JSP页面乱码<br>这种乱码的原因是应为没有在页面里指定使用的字符集编码，解决方法：只要在页面开始地方用下面代码指定字符集编码即可，&lt;%@ page contentType="text/html; charset=utf-8" %&gt;</p>
<p>2、数据库乱码<br>这种乱码会使你插入数据库的中文变成乱码，或者读出显示时也是乱码，解决方法如下：<br>在数据库连接字符串中加入编码字符集<br>String Url="jdbc:mysql://localhost/digitgulf?user=root&amp;password=root&amp;useUnicode=true&amp;characterEncoding=utf-8";<br>并在页面中使用如下代码：<br>response.setContentType("text/html;charset=utf-8");<br>request.setCharacterEncoding("utf-8");</p>
<p>3、中文作为参数传递乱码<br>当我们把一段中文字符作为参数传递个另一页面时，也会出现乱码情况，解决方法如下：<br>在参数传递时对参数编码，比如<br>RearshRes.jsp?keywords=" + java.net.URLEncoder.encode(keywords)<br>然后在接收参数页面使用如下语句接收<br>keywords=new String(request.getParameter("keywords").getBytes("8859_1"));</p>
<p>　　以上为现阶段遇到的乱码问题，乱码的核心问题还是字符集编码问题，只要掌握了这一点，一般的乱码问题都可以解决。</p>
<img src ="http://www.cnitblog.com/afa202/aggbug/60222.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/afa202/" target="_blank">火炏炎焱燚</a> 2009-07-20 10:57 <a href="http://www.cnitblog.com/afa202/archive/2009/07/20/60222.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts2 和 Servlet 耦合</title><link>http://www.cnitblog.com/afa202/archive/2009/07/20/60219.html</link><dc:creator>火炏炎焱燚</dc:creator><author>火炏炎焱燚</author><pubDate>Mon, 20 Jul 2009 02:55:00 GMT</pubDate><guid>http://www.cnitblog.com/afa202/archive/2009/07/20/60219.html</guid><wfw:comment>http://www.cnitblog.com/afa202/comments/60219.html</wfw:comment><comments>http://www.cnitblog.com/afa202/archive/2009/07/20/60219.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/afa202/comments/commentRss/60219.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/afa202/services/trackbacks/60219.html</trackback:ping><description><![CDATA[<strong><font size=5>=============================</font></strong>
<p>首选 ActionConext 其次 ServletActionContext 最后是实现接口</p>
<p><a href="http://scorpio-jh.blog.sohu.com/83673437.html"><font color=#108ac6>http://scorpio-jh.blog.sohu.com/83673437.html</font></a></p>
<p><span style="FONT-SIZE: xx-large; FONT-FAMILY: Impact"><font size=6>-- 1 --<br></font></span>&nbsp;<span style="FONT-SIZE: large; FONT-FAMILY: Georgia"><strong><font size=4>### ActionContext ###</font></strong></span>&nbsp; --- 不能获得response对象</p>
<p>static ActionContext <span style="FONT-FAMILY: Verdana"><strong>getContext()</strong></span>&nbsp;&nbsp; 获得当前线程的向下文<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 相当于<br>Object <strong><span style="FONT-FAMILY: Verdana">get(Object key)</span></strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ---- getAttribute()</p>
<p>void <span style="FONT-FAMILY: Verdana"><strong>put( Object key, Object value )</strong></span> ---- setAttribute()</p>
<p>Map <strong><span style="FONT-FAMILY: Verdana">getParameter()</span></strong>&nbsp;&nbsp;&nbsp; 相当于Servlet中的getParameterMap()</p>
<p>Map <span style="FONT-FAMILY: Verdana"><strong>getApplication()</strong></span>&nbsp;&nbsp; 对应于ServletContext</p>
<p><br>如:</p>
<p><span><span style="FONT-FAMILY: Impact">action</span>中<br></span>ActionContext.getContext().put("zhangsan","hello");</p>
<p><span><span style="FONT-FAMILY: Impact">jsp</span>中<br></span>张三：${ requestScope.zhangsan }</p>
<p>&nbsp;</p>
<p><font size=6><span style="FONT-FAMILY: Impact"><span style="FONT-SIZE: xx-large">-- 2 --</span><br></span></font><font size=5><span style="FONT-SIZE: x-large"><strong>通过接口使用</strong></span></font> --- 典型的依赖注入</p>
<p><span style="FONT-SIZE: large; FONT-FAMILY: Verdana"><font size=4>### ServletContextAware ###</font></span> 接口</p>
<p>void <strong>setServletContext( ServletContext )</strong></p>
<p><span style="FONT-SIZE: large; FONT-FAMILY: Verdana"><font size=4>### ServletRequestAware ###</font></span> 接口</p>
<p>void <strong>setServletRequest( HttpServletRequest )</strong></p>
<p><span style="FONT-SIZE: large; FONT-FAMILY: Verdana"><font size=4>### ServletResponseAware ###</font></span> 接口</p>
<p>void <strong>setServletResponse( HttpServletResponse )</strong></p>
<p><br>例：<br>public class LoginAction extends ActionSupport<br>&nbsp;implements <strong><span style="FONT-FAMILY: Verdana">ServletRequestAware</span></strong>,<br>&nbsp;&nbsp;<strong><span style="FONT-FAMILY: Verdana">ServletResponseAware</span></strong> {</p>
<p>&nbsp;private String username;<br>&nbsp;private String password;<br>&nbsp;//setter...getter...</p>
<p>&nbsp;private HttpServletRequest request;<br>&nbsp;private HttpServletResponse response;</p>
<p>&nbsp;public String execute() throws Exception {</p>
<p>&nbsp;&nbsp;//使用request对象&nbsp;<br>&nbsp;&nbsp;request.setAttribute("zhangshan","hello");</p>
<p>&nbsp;&nbsp;//使用response对象<br>&nbsp;&nbsp;Cookie cookie = new Cookie("username",<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.getUsername());<br>&nbsp;&nbsp;cookie.setMaxAge(1000);<br>&nbsp;&nbsp;response.addCookie(cookie);</p>
<p>&nbsp;&nbsp;return "success";<br>&nbsp;}</p>
<p>&nbsp;//这个方法由Strust2框架来自动调用<br>&nbsp;//调用后，便可以使用容器的request对象了<br>&nbsp;<span style="FONT-FAMILY: Courier New">public void <span style="FONT-FAMILY: Impact">setServletRequest</span>(HttpServletRequest request) {</span></p>
<p><span style="FONT-FAMILY: Courier New">&nbsp;&nbsp;this.request = request;<br>&nbsp;}</span></p>
<p>&nbsp;<span style="FONT-FAMILY: Courier New">public void <span style="FONT-FAMILY: Impact">setServletResponse</span>(HttpServletResponse responset) {</span></p>
<p><span style="FONT-FAMILY: Courier New">&nbsp;&nbsp;this.response = response;<br>&nbsp;}<br></span>}</p>
<p><br>---------------------<br><span style="FONT-FAMILY: Verdana"><strong>jsp页面中显示cookie</strong></span></p>
<p>&nbsp;cookie: ${ cookie.username.value }</p>
<p>--------------------</p>
<p><br><span style="FONT-SIZE: xx-large; FONT-FAMILY: Impact"><font size=6>-- 3 --</font></span></p>
<p>使用 org.apache.struts2.<span style="FONT-SIZE: x-large; FONT-FAMILY: Verdana"><font size=5>ServletActionContext</font></span>类<br>---继承于 com.opensymphony.xwork2.ActionContext</p>
<p>内部全部为static的方法</p>
<p>static ActionContext <strong>getActionContext</strong>(HttpServletRequest req) </p>
<p>static PageContext <strong>getPageContext</strong>()&nbsp; </p>
<p>static HttpServletRequest <strong>getRequest</strong>() <br>&nbsp;<br>static HttpServletResponse <strong>getResponse</strong>()&nbsp; </p>
<p>static ServletContext <strong>getServletContex</strong>t()&nbsp; </p>
<p>static ValueStack <strong>getValueStack</strong>(HttpServletRequest req)&nbsp; </p>
<p>-----</p>
<p>static void <strong>setRequest</strong>(HttpServletRequest request) </p>
<p>static void <strong>setResponse</strong>(HttpServletResponse response) </p>
<p>static void <strong>setServletContext</strong>(ServletContext servletContext) </p>
<p>&nbsp;</p>
<p>例：<br>public class LoginAction extends ActionSupport {</p>
<p>&nbsp;private String username;<br>&nbsp;private String password;<br>&nbsp;//setter...getter...</p>
<p>&nbsp;</p>
<p>&nbsp;public String execute() throws Exception {</p>
<p>&nbsp;&nbsp;HttpServletResponse response = <strong><span style="FONT-FAMILY: Georgia">ServletActionContext.getResponse();<br></span></strong>&nbsp;&nbsp;HttpServletRequest request = <strong><span style="FONT-FAMILY: Georgia">ServletActionContext.getRequest();</span></strong><br>&nbsp;&nbsp;HttpSession session = <strong><span style="FONT-FAMILY: Verdana">request</span></strong>.<span style="FONT-FAMILY: Verdana"><strong>getSession();</strong></span></p>
<p>&nbsp;&nbsp;return "success";<br>&nbsp;}<br>}<br><br><br><br>
<table style="TABLE-LAYOUT: fixed">
    <tbody>
        <tr>
            <td>
            <div class=cnt id=blog_text>
            <table cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td>
                        <div style="MARGIN: 13pt 0cm"><strong><font size=5><a name=_Toc75838940><span style="FONT-SIZE: 9pt; LINE-HEIGHT: 173%"><font color=#000000>ActionContext</font></span></a><span><span style="FONT-SIZE: 9pt; LINE-HEIGHT: 173%">介绍</span></span></font></strong></div>
                        <div><span style="FONT-SIZE: 9pt">在</span><span style="FONT-SIZE: 9pt">Web</span><span style="FONT-SIZE: 9pt">应用程序开发中，除了将请求参数自动设置到</span><span style="FONT-SIZE: 9pt">Action</span><span style="FONT-SIZE: 9pt">的字段中，我们往往也需要在</span><span style="FONT-SIZE: 9pt">Action</span><span style="FONT-SIZE: 9pt">里直接获取请求</span><span style="FONT-SIZE: 9pt">(Request)</span><span style="FONT-SIZE: 9pt">或会话（</span><span style="FONT-SIZE: 9pt">Session</span><span style="FONT-SIZE: 9pt">）的一些信息</span><span style="FONT-SIZE: 9pt">, </span><span style="FONT-SIZE: 9pt">甚至需要直接对</span><span style="FONT-SIZE: 9pt">JavaServlet Http</span><span style="FONT-SIZE: 9pt">的请求（</span><span style="FONT-SIZE: 9pt">HttpServletRequest</span><span style="FONT-SIZE: 9pt">）、响应</span><span style="FONT-SIZE: 9pt">(HttpServletResponse)</span><span style="FONT-SIZE: 9pt">操作。</span></div>
                        <div><span style="FONT-SIZE: 9pt">我们需要在</span><span style="FONT-SIZE: 9pt">Action</span><span style="FONT-SIZE: 9pt">中取得</span><span style="FONT-SIZE: 9pt">request</span><span style="FONT-SIZE: 9pt">请求参数&#8220;</span><span style="FONT-SIZE: 9pt">username</span><span style="FONT-SIZE: 9pt">&#8221;的值：</span></div>
                        <div style="TEXT-INDENT: 21pt"><span style="FONT-SIZE: 9pt">ActionContext context = ActionContext.getContext();</span></div>
                        <div style="TEXT-INDENT: 21pt"><span style="FONT-SIZE: 9pt">Map params = context.getParameters();</span></div>
                        <div style="TEXT-INDENT: 21pt"><span style="FONT-SIZE: 9pt">String username = (String) params.get(&#8220;username&#8221;);</span></div>
                        <div><span style="FONT-SIZE: 9pt">ActionContext</span><span style="FONT-SIZE: 9pt">（</span><span style="FONT-SIZE: 9pt">com.opensymphony.xwork.ActionContext</span><span style="FONT-SIZE: 9pt">）是</span><span style="FONT-SIZE: 9pt">Action</span><span style="FONT-SIZE: 9pt">执行时的上下文，上下文可以看作是一个容器（其实我们这里的容器就是一个</span><span style="FONT-SIZE: 9pt">Map</span><span style="FONT-SIZE: 9pt">而已），它存放放的是</span><span style="FONT-SIZE: 9pt">Action</span><span style="FONT-SIZE: 9pt">在执行时需要用到的对象</span></div>
                        <div></div>
                        <div><span style="FONT-SIZE: 9pt">一般情况，我们的</span><span style="FONT-SIZE: 9pt">ActionContext</span><span style="FONT-SIZE: 9pt">都是通过：</span><span style="FONT-SIZE: 9pt">ActionContext context = (ActionContext) actionContext.get();</span><span style="FONT-SIZE: 9pt">来获取的。我们再来看看这里的</span><span style="FONT-SIZE: 9pt">actionContext</span><span style="FONT-SIZE: 9pt">对象的创建：</span><span style="FONT-SIZE: 9pt">static ThreadLocal actionContext = new ActionContextThreadLocal();</span><span style="FONT-SIZE: 9pt">，</span><span style="FONT-SIZE: 9pt">ActionContextThreadLocal</span><span style="FONT-SIZE: 9pt">是实现</span><span style="FONT-SIZE: 9pt">ThreadLocal</span><span style="FONT-SIZE: 9pt">的一个内部类。</span><span style="FONT-SIZE: 9pt">ThreadLocal</span><span style="FONT-SIZE: 9pt">可以命名为&#8220;线程局部变量&#8221;，它为每一个使用该变量的线程都提供一个变量值的副本，使每一个线程都可以独立地改变自己的副本，而不会和其它线程的副本冲突。这样，我们</span><span style="FONT-SIZE: 9pt">ActionContext</span><span style="FONT-SIZE: 9pt">里的属性只会在对应的当前请求线程中可见，从而保证它是线程安全的。</span></div>
                        <div></div>
                        <div></div>
                        <div><span style="FONT-SIZE: 9pt">下面我们看看怎么通过</span><span style="FONT-SIZE: 9pt">ActionContext</span><span style="FONT-SIZE: 9pt">取得我们的</span><span style="FONT-SIZE: 9pt">HttpSession</span><span style="FONT-SIZE: 9pt">：</span></div>
                        <div style="TEXT-INDENT: 4.5pt"><span style="FONT-SIZE: 9pt">Map session = ActionContext.getContext().getSession()</span><span style="FONT-SIZE: 9pt">；</span></div>
                        <div></div>
                        <div style="MARGIN: 13pt 0cm"><strong><font color=#000000 size=5><a name=_Toc75838941><span style="FONT-SIZE: 9pt; LINE-HEIGHT: 173%">ServletActionContext</span></a></font></strong></div>
                        <div style="TEXT-INDENT: 18pt"><span style="FONT-SIZE: 9pt">ServletActionContext</span><span style="FONT-SIZE: 9pt">（</span><span style="FONT-SIZE: 9pt">com.opensymphony.webwork. ServletActionContext</span><span style="FONT-SIZE: 9pt">），这个类直接继承了我们上面介绍的</span><span style="FONT-SIZE: 9pt">ActionContext</span><span style="FONT-SIZE: 9pt">，它提供了直接与</span><span style="FONT-SIZE: 9pt">JavaServlet</span><span style="FONT-SIZE: 9pt">相关对象访问的功能，它可以取得的对象有：</span></div>
                        <div style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt"><span style="FONT-SIZE: 9pt">1、<span style="FONT: 7pt -Times New Roman-; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;</span></span><span style="FONT-SIZE: 9pt">javax.servlet.http.HttpServletRequest</span><span style="FONT-SIZE: 9pt">：</span><span style="FONT-SIZE: 9pt">HTTPservlet</span><span style="FONT-SIZE: 9pt">请求对象</span></div>
                        <div style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt"><span style="FONT-SIZE: 9pt">2、<span style="FONT: 7pt -Times New Roman-; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;</span></span><span style="FONT-SIZE: 9pt">javax.servlet.http.HttpServletResponse;</span><span style="FONT-SIZE: 9pt">：</span><span style="FONT-SIZE: 9pt">HTTPservlet</span><span style="FONT-SIZE: 9pt">相应对象</span></div>
                        <div style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt"><span style="FONT-SIZE: 9pt">3、<span style="FONT: 7pt -Times New Roman-; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;</span></span><span style="FONT-SIZE: 9pt">javax.servlet.ServletContext</span><span style="FONT-SIZE: 9pt">：</span><span style="FONT-SIZE: 9pt">Servlet </span><span style="FONT-SIZE: 9pt">上下文信息</span></div>
                        <div style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt"><span style="FONT-SIZE: 9pt">4、<span style="FONT: 7pt -Times New Roman-; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;</span></span><span style="FONT-SIZE: 9pt">javax.servlet.ServletConfig</span><span style="FONT-SIZE: 9pt">：</span><span style="FONT-SIZE: 9pt">Servlet</span><span style="FONT-SIZE: 9pt">配置对象</span></div>
                        <div style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt"><span style="FONT-SIZE: 9pt">5、<span style="FONT: 7pt -Times New Roman-; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;</span></span><span style="FONT-SIZE: 9pt">javax.servlet.jsp.PageContext</span><span style="FONT-SIZE: 9pt">：</span><span style="FONT-SIZE: 9pt">Http</span><span style="FONT-SIZE: 9pt">页面上下文</span></div>
                        <div style="TEXT-INDENT: 18pt"></div>
                        <div style="TEXT-INDENT: 18pt"></div>
                        <div style="TEXT-INDENT: 18pt"><span style="FONT-SIZE: 9pt">下面我们看看几个简单的例子，让我们了解如何从</span><span style="FONT-SIZE: 9pt">ServletActionContext</span><span style="FONT-SIZE: 9pt">里取得</span><span style="FONT-SIZE: 9pt">JavaServlet</span><span style="FONT-SIZE: 9pt">的相关对象：</span></div>
                        <div style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt"><strong><span style="FONT-SIZE: 9pt">1、<span style="FONT: 7pt -Times New Roman-; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;</span></span></strong><span style="FONT-SIZE: 9pt">取得</span><span style="FONT-SIZE: 9pt">HttpServletRequest</span><span style="FONT-SIZE: 9pt">对象：</span></div>
                        <div style="MARGIN: 0cm 0cm 0pt 39pt"><span style="FONT-SIZE: 9pt">HttpServletRequest request = ServletActionContext. getRequest();</span></div>
                        <div style="MARGIN: 0cm 0cm 0pt 39pt; TEXT-INDENT: -18pt"><strong><span style="FONT-SIZE: 9pt">2、<span style="FONT: 7pt -Times New Roman-; font-size-adjust: none; font-stretch: normal">&nbsp;&nbsp;&nbsp;</span></span></strong><span style="FONT-SIZE: 9pt">取得</span><span style="FONT-SIZE: 9pt">HttpSession</span><span style="FONT-SIZE: 9pt">对象：</span></div>
                        <div style="MARGIN: 0cm 0cm 0pt 39pt"><span style="FONT-SIZE: 9pt">HttpSession session = ServletActionContext. getRequest().getSession();</span></div>
                        <div></div>
                        <div><span style="FONT-SIZE: 9pt">ServletActionContext</span><span style="FONT-SIZE: 9pt">和</span><span style="FONT-SIZE: 9pt">ActionContext</span><span style="FONT-SIZE: 9pt">有着一些重复的功能，在我们的</span><span style="FONT-SIZE: 9pt">Action</span><span style="FONT-SIZE: 9pt">中，该如何去抉择呢？我们遵循的原则是：如果</span><span style="FONT-SIZE: 9pt">ActionContext</span><span style="FONT-SIZE: 9pt">能够实现我们的功能，那最好就不要使用</span><span style="FONT-SIZE: 9pt">ServletActionContext</span><span style="FONT-SIZE: 9pt">，让我们的</span><span style="FONT-SIZE: 9pt">Action</span><span style="FONT-SIZE: 9pt">尽量不要直接去访问</span><span style="FONT-SIZE: 9pt">JavaServlet</span><span style="FONT-SIZE: 9pt">的相关对象。在使用</span><span style="FONT-SIZE: 9pt">ActionContext</span><span style="FONT-SIZE: 9pt">时有一点要注意：不要在</span><span style="FONT-SIZE: 9pt">Action</span><span style="FONT-SIZE: 9pt">的构造函数里使用</span><span style="FONT-SIZE: 9pt">ActionContext.getContext()</span><span style="FONT-SIZE: 9pt">，因为这个时候</span><span style="FONT-SIZE: 9pt">ActionContext</span><span style="FONT-SIZE: 9pt">里的一些值也许没有设置，这时通过</span><span style="FONT-SIZE: 9pt">ActionContext</span><span style="FONT-SIZE: 9pt">取得的值也许是</span><span style="FONT-SIZE: 9pt">null</span><span style="FONT-SIZE: 9pt">。</span></div>
                        </td>
                    </tr>
                </tbody>
            </table>
            </div>
            </td>
        </tr>
    </tbody>
</table>
</p>
<img src ="http://www.cnitblog.com/afa202/aggbug/60219.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/afa202/" target="_blank">火炏炎焱燚</a> 2009-07-20 10:55 <a href="http://www.cnitblog.com/afa202/archive/2009/07/20/60219.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>excel导出</title><link>http://www.cnitblog.com/afa202/archive/2008/07/17/46808.html</link><dc:creator>火炏炎焱燚</dc:creator><author>火炏炎焱燚</author><pubDate>Thu, 17 Jul 2008 01:23:00 GMT</pubDate><guid>http://www.cnitblog.com/afa202/archive/2008/07/17/46808.html</guid><wfw:comment>http://www.cnitblog.com/afa202/comments/46808.html</wfw:comment><comments>http://www.cnitblog.com/afa202/archive/2008/07/17/46808.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/afa202/comments/commentRss/46808.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/afa202/services/trackbacks/46808.html</trackback:ping><description><![CDATA[<p>//输出类<br>package em.util;</p>
<p>import java.io.*;</p>
<p>import jxl.LabelCell;<br>import jxl.Workbook;<br>import jxl.write.Label;<br>import jxl.write.WritableCellFormat;<br>import jxl.write.WritableSheet;<br>import jxl.write.WritableWorkbook;<br>import jxl.write.WriteException;<br>import jxl.write.biff.RowsExceededException;<br>import jxl.write.Number;<br>import jxl.write.Boolean;<br>import jxl.write.DateTime;<br>import jxl.write.DateFormats;<br>import java.util.Date;<br>import java.util.List;</p>
<p>import java.io.IOException;<br>import java.util.List;</p>
<p>import javax.servlet.ServletException;<br>import javax.servlet.http.HttpServlet;<br>import javax.servlet.http.HttpServletRequest;<br>import javax.servlet.http.HttpServletResponse;</p>
<p>import jxl.Workbook;<br>import jxl.format.Alignment;<br>import jxl.format.Border;<br>import jxl.format.BorderLineStyle;<br>import jxl.format.Colour;<br>import jxl.format.VerticalAlignment;<br>import jxl.write.Label;<br>import jxl.write.WritableCellFormat;<br>import jxl.write.WritableFont;<br>import jxl.write.WritableSheet;<br>import jxl.write.WritableWorkbook;</p>
<p>import jxl.write.NumberFormats;<br>import java.util.Calendar;<br>import java.text.SimpleDateFormat;<br>import java.io.*;<br>import java.util.*;</p>
<p>public class ComplexDataExcelWrite {</p>
<p>&nbsp;private WritableFont NormalFont, BoldFont, tableFont, baodanFont;<br>&nbsp;private WritableCellFormat wcf_title, wcf_tabletitle, wcf_baodan, wcf_left, wcf_center;<br>&nbsp;private WritableCellFormat wcf_merge, wcf_right, wcf_table, dtCellFormat;<br>&nbsp;private static ComplexDataExcelWrite instance = null;</p>
<p>&nbsp;private ComplexDataExcelWrite() {</p>
<p>&nbsp;}</p>
<p>&nbsp;public static synchronized ComplexDataExcelWrite getInstance() throws WriteException, IOException {</p>
<p>&nbsp;&nbsp;try {<br>&nbsp;&nbsp;&nbsp;if (instance == null) {<br>&nbsp;&nbsp;&nbsp;&nbsp;instance = new ComplexDataExcelWrite();<br>&nbsp;&nbsp;&nbsp;&nbsp;instance.formatFont();<br>&nbsp;&nbsp;&nbsp;&nbsp;instance.formatTableCell();</p>
<p>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;return instance;<br>&nbsp;&nbsp;} catch (Exception e) {<br>&nbsp;&nbsp;&nbsp;return null;<br>&nbsp;&nbsp;}</p>
<p>&nbsp;}</p>
<p>&nbsp;private void formatFont() {<br>&nbsp;&nbsp;/** ************设置单元格字体************** */<br>&nbsp;&nbsp;// 字体<br>&nbsp;&nbsp;NormalFont = new WritableFont(WritableFont.ARIAL, 10);<br>&nbsp;&nbsp;BoldFont = new WritableFont(WritableFont.ARIAL, 14, WritableFont.BOLD);<br>&nbsp;&nbsp;tableFont = new WritableFont(WritableFont.ARIAL, 12, WritableFont.NO_BOLD);<br>&nbsp;&nbsp;baodanFont = new WritableFont(WritableFont.ARIAL, 10, WritableFont.BOLD);<br>&nbsp;}</p>
<p>&nbsp;private void formatTableCell() throws WriteException, IOException {<br>&nbsp;&nbsp;/** ************以下设置几种格式的单元格************ */<br>&nbsp;&nbsp;try {<br>&nbsp;&nbsp;&nbsp;// 用于标题<br>&nbsp;&nbsp;&nbsp;wcf_title = new WritableCellFormat(BoldFont);<br>&nbsp;&nbsp;&nbsp;wcf_title.setBorder(Border.NONE, BorderLineStyle.THIN); // 线条<br>&nbsp;&nbsp;&nbsp;wcf_title.setVerticalAlignment(VerticalAlignment.CENTRE); // 垂直对齐<br>&nbsp;&nbsp;&nbsp;wcf_title.setAlignment(Alignment.CENTRE); // 水平对齐<br>&nbsp;&nbsp;&nbsp;wcf_title.setWrap(true); // 是否换行</p>
<p>&nbsp;&nbsp;&nbsp;// 用于标题<br>&nbsp;&nbsp;&nbsp;wcf_tabletitle = new WritableCellFormat(tableFont);<br>&nbsp;&nbsp;&nbsp;wcf_tabletitle.setBorder(Border.NONE, BorderLineStyle.THIN); // 线条<br>&nbsp;&nbsp;&nbsp;wcf_tabletitle.setVerticalAlignment(VerticalAlignment.CENTRE); // 垂直对齐<br>&nbsp;&nbsp;&nbsp;wcf_tabletitle.setAlignment(Alignment.CENTRE); // 水平对齐<br>&nbsp;&nbsp;&nbsp;wcf_tabletitle.setWrap(true); // 是否换行</p>
<p>&nbsp;&nbsp;&nbsp;// 用于保单标题<br>&nbsp;&nbsp;&nbsp;wcf_baodan = new WritableCellFormat(baodanFont);<br>&nbsp;&nbsp;&nbsp;wcf_baodan.setBorder(Border.ALL, BorderLineStyle.THIN); // 线条<br>&nbsp;&nbsp;&nbsp;wcf_baodan.setVerticalAlignment(VerticalAlignment.CENTRE); // 垂直对齐<br>&nbsp;&nbsp;&nbsp;wcf_baodan.setAlignment(Alignment.CENTRE);<br>&nbsp;&nbsp;&nbsp;wcf_baodan.setWrap(true); // 是否换行</p>
<p>&nbsp;&nbsp;&nbsp;// 用于正文左<br>&nbsp;&nbsp;&nbsp;wcf_left = new WritableCellFormat(NormalFont);<br>&nbsp;&nbsp;&nbsp;wcf_left.setBorder(Border.ALL, BorderLineStyle.THIN); // 线条<br>&nbsp;&nbsp;&nbsp;wcf_left.setVerticalAlignment(VerticalAlignment.CENTRE); // 垂直对齐<br>&nbsp;&nbsp;&nbsp;wcf_left.setAlignment(Alignment.LEFT);<br>&nbsp;&nbsp;&nbsp;wcf_left.setWrap(true); // 是否换行</p>
<p>&nbsp;&nbsp;&nbsp;// 用于正文左<br>&nbsp;&nbsp;&nbsp;wcf_center = new WritableCellFormat(NormalFont);<br>&nbsp;&nbsp;&nbsp;wcf_center.setBorder(Border.ALL, BorderLineStyle.THIN); // 线条<br>&nbsp;&nbsp;&nbsp;wcf_center.setVerticalAlignment(VerticalAlignment.CENTRE); // 垂直对齐<br>&nbsp;&nbsp;&nbsp;wcf_center.setAlignment(Alignment.CENTRE);<br>&nbsp;&nbsp;&nbsp;wcf_center.setWrap(true); // 是否换行</p>
<p>&nbsp;&nbsp;&nbsp;// 用于正文右<br>&nbsp;&nbsp;&nbsp;wcf_right = new WritableCellFormat(NormalFont);<br>&nbsp;&nbsp;&nbsp;wcf_right.setBorder(Border.ALL, BorderLineStyle.THIN); // 线条<br>&nbsp;&nbsp;&nbsp;wcf_right.setVerticalAlignment(VerticalAlignment.CENTRE); // 垂直对齐<br>&nbsp;&nbsp;&nbsp;wcf_right.setAlignment(Alignment.RIGHT);<br>&nbsp;&nbsp;&nbsp;wcf_right.setWrap(false); // 是否换行</p>
<p>&nbsp;&nbsp;&nbsp;// 用于跨行<br>&nbsp;&nbsp;&nbsp;wcf_merge = new WritableCellFormat(NormalFont);<br>&nbsp;&nbsp;&nbsp;wcf_merge.setBorder(Border.ALL, BorderLineStyle.THIN); // 线条<br>&nbsp;&nbsp;&nbsp;wcf_merge.setVerticalAlignment(VerticalAlignment.TOP); // 垂直对齐<br>&nbsp;&nbsp;&nbsp;wcf_merge.setAlignment(Alignment.LEFT);<br>&nbsp;&nbsp;&nbsp;wcf_merge.setWrap(true); // 是否换行</p>
<p>&nbsp;&nbsp;&nbsp;wcf_table = new WritableCellFormat(NormalFont);<br>&nbsp;&nbsp;&nbsp;wcf_table.setBorder(Border.ALL, BorderLineStyle.THIN); // 线条<br>&nbsp;&nbsp;&nbsp;wcf_table.setVerticalAlignment(VerticalAlignment.CENTRE); // 垂直对齐<br>&nbsp;&nbsp;&nbsp;wcf_table.setAlignment(Alignment.CENTRE);<br>&nbsp;&nbsp;&nbsp;wcf_table.setBackground(Colour.GRAY_25);<br>&nbsp;&nbsp;&nbsp;wcf_table.setWrap(true); // 是否换行</p>
<p>&nbsp;&nbsp;&nbsp;// 时间格式<br>&nbsp;&nbsp;&nbsp;dtCellFormat = new WritableCellFormat(DateFormats.FORMAT1);<br>&nbsp;&nbsp;&nbsp;dtCellFormat.setBorder(Border.ALL, BorderLineStyle.THIN); // 线条<br>&nbsp;&nbsp;&nbsp;dtCellFormat.setVerticalAlignment(VerticalAlignment.CENTRE); // 垂直对齐<br>&nbsp;&nbsp;&nbsp;dtCellFormat.setAlignment(Alignment.CENTRE);<br>&nbsp;&nbsp;&nbsp;dtCellFormat.setBackground(Colour.GRAY_25);<br>&nbsp;&nbsp;&nbsp;dtCellFormat.setWrap(true); // 是否换行<br>&nbsp;&nbsp;} catch (Exception e) {</p>
<p>&nbsp;&nbsp;}<br>&nbsp;}</p>
<p>&nbsp;private void formatSheetColView(WritableSheet sheet) throws WriteException, IOException {<br>&nbsp;&nbsp;try {<br>&nbsp;&nbsp;&nbsp;/** *********设置列宽**************** */<br>&nbsp;&nbsp;&nbsp;sheet.setColumnView(0, 15); // 第1列<br>&nbsp;&nbsp;&nbsp;sheet.setColumnView(1, 15); // 第2列<br>&nbsp;&nbsp;&nbsp;sheet.setColumnView(2, 15);<br>&nbsp;&nbsp;&nbsp;sheet.setColumnView(3, 15);<br>&nbsp;&nbsp;&nbsp;sheet.setColumnView(4, 15);<br>&nbsp;&nbsp;&nbsp;sheet.setColumnView(5, 15);</p>
<p>&nbsp;&nbsp;&nbsp;// 设置页边距<br>&nbsp;&nbsp;&nbsp;sheet.getSettings().setRightMargin(0.5);<br>&nbsp;&nbsp;} catch (Exception e) {<br>&nbsp;&nbsp;&nbsp;// TODO: handle exception<br>&nbsp;&nbsp;}<br>&nbsp;}</p>
<p>&nbsp;public void creatExcel(List list, OutputStream os) throws WriteException, IOException {<br>&nbsp;&nbsp;try {<br>&nbsp;&nbsp;&nbsp;WritableWorkbook workbook = Workbook.createWorkbook(os);</p>
<p>&nbsp;&nbsp;&nbsp;WritableSheet sheet = workbook.createSheet("first sheet", 0);</p>
<p>&nbsp;&nbsp;&nbsp;formatSheetColView(sheet);<br>&nbsp;&nbsp;&nbsp;// 添加主体<br>&nbsp;&nbsp;&nbsp;int rowNum = 0;<br>&nbsp;&nbsp;&nbsp;for (Iterator it = list.iterator(); it.hasNext();) {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;rowNum += 1;<br>&nbsp;&nbsp;&nbsp;&nbsp;// 设置行高<br>&nbsp;&nbsp;&nbsp;&nbsp;sheet.setRowView(rowNum, 400, false);<br>&nbsp;&nbsp;&nbsp;&nbsp;String[] str = (String[]) it.next();<br>&nbsp;&nbsp;&nbsp;&nbsp;for (int i = 0; i &lt; str.length; i++) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Label example = new Label(i, rowNum, str[i], wcf_table);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sheet.addCell(example);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;workbook.write();<br>&nbsp;&nbsp;&nbsp;workbook.close();<br>&nbsp;&nbsp;&nbsp;os.close();<br>&nbsp;&nbsp;} catch (Exception e) {</p>
<p>&nbsp;&nbsp;}<br>&nbsp;}</p>
<p>&nbsp;public void creatExcel(String sheetName, String[] title, List list, OutputStream os) throws WriteException, IOException {<br>&nbsp;&nbsp;try {<br>&nbsp;&nbsp;&nbsp;WritableWorkbook workbook = Workbook.createWorkbook(os);</p>
<p>&nbsp;&nbsp;&nbsp;WritableSheet sheet = workbook.createSheet(sheetName, 0);</p>
<p>&nbsp;&nbsp;&nbsp;formatSheetColView(sheet);<br>&nbsp;&nbsp;&nbsp;formatFont();<br>&nbsp;&nbsp;&nbsp;formatTableCell();<br>&nbsp;&nbsp;&nbsp;/** ****** 填充数据 ******** */</p>
<p>&nbsp;&nbsp;&nbsp;// 添加标题，第一行<br>&nbsp;&nbsp;&nbsp;sheet.mergeCells(0, 0, title.length - 1, 0);<br>&nbsp;&nbsp;&nbsp;Label titleLabel;<br>&nbsp;&nbsp;&nbsp;if (sheetName == null) {<br>&nbsp;&nbsp;&nbsp;&nbsp;titleLabel = new Label(0, 0, "sheetName", wcf_baodan);</p>
<p>&nbsp;&nbsp;&nbsp;} else {<br>&nbsp;&nbsp;&nbsp;&nbsp;titleLabel = new Label(0, 0, sheetName, wcf_baodan);<br>&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;// 设置行高<br>&nbsp;&nbsp;&nbsp;sheet.setRowView(0, 400, false);</p>
<p>&nbsp;&nbsp;&nbsp;sheet.addCell(titleLabel);</p>
<p>&nbsp;&nbsp;&nbsp;// 添加表头<br>&nbsp;&nbsp;&nbsp;for (int i = 0; i &lt; title.length; i++) {<br>&nbsp;&nbsp;&nbsp;&nbsp;Label formate = new Label(i, 1, title[i], wcf_tabletitle);<br>&nbsp;&nbsp;&nbsp;&nbsp;sheet.addCell(formate);</p>
<p>&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;// 添加主体<br>&nbsp;&nbsp;&nbsp;int rowNum = 1;<br>&nbsp;&nbsp;&nbsp;for (Iterator it = list.iterator(); it.hasNext();) {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;rowNum += 1;<br>&nbsp;&nbsp;&nbsp;&nbsp;// 设置行高<br>&nbsp;&nbsp;&nbsp;&nbsp;sheet.setRowView(rowNum, 400, false);<br>&nbsp;&nbsp;&nbsp;&nbsp;String[] str = (String[]) it.next();<br>&nbsp;&nbsp;&nbsp;&nbsp;for (int i = 0; i &lt; str.length; i++) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Label example = new Label(i, rowNum, str[i], wcf_table);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sheet.addCell(example);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;workbook.write();<br>&nbsp;&nbsp;&nbsp;workbook.close();</p>
<p>&nbsp;&nbsp;&nbsp;workbook = null;<br>&nbsp;&nbsp;&nbsp;sheet = null;<br>&nbsp;&nbsp;} catch (RuntimeException e) {<br>&nbsp;&nbsp;&nbsp;e.printStackTrace();<br>&nbsp;&nbsp;}<br>&nbsp;}<br>}<br><br><br>//调用类<br>try {</p>
<p>&nbsp;&nbsp;&nbsp;List resultItems = new ArrayList();<br>&nbsp;&nbsp;&nbsp;resultItems.clear();<br>&nbsp;&nbsp;&nbsp;String[] title = { "第一列", "第二列", "第三列", "第四列" };<br>&nbsp;&nbsp;&nbsp;String[] s1 = { "11", "12", "13", "14" };<br>&nbsp;&nbsp;&nbsp;String[] s2 = { "21", "22", "23", "24" };<br>&nbsp;&nbsp;&nbsp;resultItems.add(s1);<br>&nbsp;&nbsp;&nbsp;resultItems.add(s2);</p>
<p>&nbsp;&nbsp;&nbsp;OutputStream os = response.getOutputStream();</p>
<p>&nbsp;&nbsp;&nbsp;response.reset();<br>&nbsp;&nbsp;&nbsp;String fname = "学校专业竞争力情况";<br>&nbsp;&nbsp;&nbsp;response.setCharacterEncoding("UTF-8");<br>&nbsp;&nbsp;&nbsp;fname = URLEncoder.encode(fname, "UTF-8");<br>&nbsp;&nbsp;&nbsp;response.setHeader("Content-Disposition", "attachment;filename=" + new String(fname.getBytes("UTF-8"), "GBK") + ".XLS");<br>&nbsp;&nbsp;&nbsp;response.setContentType("application/msexcel");<br>&nbsp;&nbsp;&nbsp;ComplexDataExcelWrite.getInstance().creatExcel("标题", title, resultItems, os);</p>
<p>&nbsp;&nbsp;&nbsp;//ComplexDataExcelWrite sw=new ComplexDataExcelWrite();<br>&nbsp;&nbsp;//&nbsp;sw.creatExcel("标题", title, resultItems, os);</p>
<p>&nbsp;&nbsp;} catch (Exception e) {<br>&nbsp;&nbsp;&nbsp;// TODO: handle exception<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;return null;<br><br>//如果用jsp直接调用，注意out的处理方法，用他屏蔽一个<font size=3><u><font color=#c60a00>getOutputStream</font><font color=#800080>() </font><font color=#c60a00>has</font><font color=#800080> </font><font color=#c60a00>already</font><font color=#800080> </font><font color=#c60a00>been</font><font color=#800080> </font><font color=#c60a00>called</font><font color=#800080> </font><font color=#c60a00>for</font><font color=#800080> </font><font color=#c60a00>this</font><font color=#800080> </font><font color=#c60a00>response<br></font></u></font>//异常<br>&lt;%@ page language="java" import="java.util.*" pageEncoding="gbk"%&gt;<br>&lt;%@ page import="java.io.*"%&gt;<br>&lt;<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#37;&#64;&#112;&#97;&#103;&#101;">%@page</a> import="java.net.URLEncoder"%&gt;<br>&lt;<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#37;&#64;&#112;&#97;&#103;&#101;">%@page</a> import="em.util.ComplexDataExcelWrite"%&gt;<br>&lt;%<br>&nbsp;List resultItems = new ArrayList();<br>&nbsp;resultItems.clear();<br>&nbsp;String[] title = { "第一列", "第二列", "第三列", "第四列" };<br>&nbsp;String[] s1 = { "11", "12", "13", "14" };<br>&nbsp;String[] s2 = { "21", "22", "23", "24" };<br>&nbsp;resultItems.add(s1);<br>&nbsp;resultItems.add(s2);</p>
<p>&nbsp;OutputStream os = response.getOutputStream();<br>&nbsp;response.reset();<br>&nbsp;String fname = "学校专业竞争力情况";<br>&nbsp;response.setCharacterEncoding("UTF-8");<br>&nbsp;fname = URLEncoder.encode(fname, "UTF-8");<br>&nbsp;response.setHeader("Content-Disposition", "attachment;filename=" + new String(fname.getBytes("UTF-8"), "GBK") + ".XLS");<br>&nbsp;response.setContentType("application/msexcel");</p>
<p>&nbsp;ComplexDataExcelWrite.getInstance().creatExcel("标题", title, resultItems, os);<br><span style="COLOR: red">&nbsp;out.clear();<br>&nbsp;out = pageContext.pushBody();</span></p>
<p>&nbsp;//ComplexDataExcelWrite sw=new ComplexDataExcelWrite();<br>&nbsp;//&nbsp;sw.creatExcel("标题", title, resultItems, os);<br>%&gt;<br>&lt;html&gt;<br>&nbsp;&lt;head&gt;<br>&nbsp;&nbsp;&lt;META HTTP-EQUIV="Pragma" CONTENT="no-cache"&gt;<br>&nbsp;&nbsp;&lt;META HTTP-EQUIV="Cache-Control" CONTENT="no-cache"&gt;<br>&nbsp;&nbsp;&lt;META HTTP-EQUIV="Expires" CONTENT="0"&gt;<br>&nbsp;&lt;/head&gt;<br>&lt;/html&gt;</p>
<img src ="http://www.cnitblog.com/afa202/aggbug/46808.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/afa202/" target="_blank">火炏炎焱燚</a> 2008-07-17 09:23 <a href="http://www.cnitblog.com/afa202/archive/2008/07/17/46808.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate条件查询(Criteria Query) </title><link>http://www.cnitblog.com/afa202/archive/2008/05/05/43336.html</link><dc:creator>火炏炎焱燚</dc:creator><author>火炏炎焱燚</author><pubDate>Mon, 05 May 2008 03:23:00 GMT</pubDate><guid>http://www.cnitblog.com/afa202/archive/2008/05/05/43336.html</guid><wfw:comment>http://www.cnitblog.com/afa202/comments/43336.html</wfw:comment><comments>http://www.cnitblog.com/afa202/archive/2008/05/05/43336.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/afa202/comments/commentRss/43336.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/afa202/services/trackbacks/43336.html</trackback:ping><description><![CDATA[<div class=postTitle twffan="done">&nbsp;</div>
<div class=postText twffan="done">
<p><font size=2><font color=#000000><strong>1、创建一个Criteria实例</strong><br>net.sf.hibernate.Criteria这个接口代表对一个特定的持久化类的查询。Session是用来制造Criteria实例的工厂。&nbsp;</font></font></p>
<p><font color=#000000 size=2>Criteria&nbsp;crit&nbsp;=&nbsp;sess.createCriteria(Cat.class);//创建实力类可以为OBJECT.CLASS<br>crit.setMaxResults(50);<br>List&nbsp;cats&nbsp;=&nbsp;crit.list();</font></p>
<p><font color=#000000 size=2>返回最多50条记录的结果集。</font></p>
<p><font size=2><font color=#000000><strong>2、缩小结果集范围</strong><br>一个查询条件(Criterion)是net.sf.hibernate.expression.Criterion接口的一个实例。类net.sf.hibernate.expression.Expression定义了获得一些内置的Criterion类型。&nbsp;<br><br><br>import org.hibernate.criterion.Projections;//两个查询条件类<br>import org.hibernate.criterion.Expression;</font></font></p>
<p><font color=#000000 size=2>List&nbsp;cats&nbsp;=&nbsp;sess.createCriteria(Cat.class)<br>&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.like("name",&nbsp;"Fritz%")&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.between("weight",&nbsp;minWeight,&nbsp;maxWeight)&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;.list();<br>表达式（Expressions）可以按照逻辑分组.&nbsp;</font></p>
<p><font color=#000000 size=2>List&nbsp;cats&nbsp;=&nbsp;sess.createCriteria(Cat.class)<br>&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.like("name",&nbsp;"Fritz%")&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.or(<br>&nbsp;&nbsp;&nbsp;&nbsp; Expression.eq(&nbsp;"age",&nbsp;new&nbsp;Integer(0)&nbsp;),<br>&nbsp;&nbsp;&nbsp;&nbsp; Expression.isNull("age")<br>&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;.list();</font></p>
<p><font color=#000000 size=2>返回（name like "Fritz%" and age 等于0 或者 age 为空）的结果集<br><br><br>List&nbsp;cats&nbsp;=&nbsp;sess.createCriteria(Cat.class)<br>&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.in(&nbsp;"name",&nbsp;new&nbsp;String[]&nbsp;{&nbsp;"Fritz",&nbsp;"Izi",&nbsp;"Pk"&nbsp;}&nbsp;)&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.disjunction()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.isNull("age")&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp; .add(&nbsp;Expression.eq("age",&nbsp;new&nbsp;Integer(0)&nbsp;)&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp; .add(&nbsp;Expression.eq("age",&nbsp;new&nbsp;Integer(1)&nbsp;)&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp; .add(&nbsp;Expression.eq("age",&nbsp;new&nbsp;Integer(2)&nbsp;)&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;)&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;.list();</font></p>
<p><font color=#000000 size=2>Expression.disjunction()----意思是可以按照逻辑分组<br>有很多预制的条件类型（Expression的子类）。有一个特别有用，可以让你直接嵌入SQL。&nbsp;</font></p>
<p><font color=#000000 size=2>List&nbsp;cats&nbsp;=&nbsp;sess.createCriteria(Cat.class)<br>&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.sql("lower($alias.name)&nbsp;like&nbsp;lower(?)",&nbsp;"Fritz%",&nbsp;Hibernate.STRING)&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;.list();<br>其中的{alias}是一个占位符，它将会被所查询实体的行别名所替代。(原文:The&nbsp;{alias}&nbsp;placeholder&nbsp;with&nbsp;be&nbsp;replaced&nbsp;by&nbsp;the&nbsp;row&nbsp;alias&nbsp;of&nbsp;the&nbsp;queried&nbsp;entity.)&nbsp;</font></p>
<p><font size=2><font color=#000000><strong>3、对结果排序</strong><br>可以使用net.sf.hibernate.expression.Order对结果集排序.&nbsp;</font></font></p>
<p><font color=#000000 size=2>List&nbsp;cats&nbsp;=&nbsp;sess.createCriteria(Cat.class)<br>&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.like("name",&nbsp;"F%")<br>&nbsp;&nbsp;&nbsp;&nbsp;.addOrder(&nbsp;Order.asc("name")&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;.addOrder(&nbsp;Order.desc("age")&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;.setMaxResults(50)<br>&nbsp;&nbsp;&nbsp;&nbsp;.list();<br><strong>4、关联（Associations）</strong><br>你可以在关联之间使用createCriteria()，很容易地在存在关系的实体之间指定约束。&nbsp;</font></p>
<p><font color=#000000 size=2>List&nbsp;cats&nbsp;=&nbsp;sess.createCriteria(Cat.class)<br>&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.like("name",&nbsp;"F%")<br>&nbsp;&nbsp;&nbsp;&nbsp;.createCriteria("kittens")<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.like("name",&nbsp;"F%")<br>&nbsp;&nbsp;&nbsp;&nbsp;.list();<br>注意，第二个createCriteria()返回一个Criteria的新实例，指向kittens集合类的元素。&nbsp;</font></p>
<p><font color=#000000 size=2>下面的替代形式在特定情况下有用。&nbsp;</font></p>
<p><font color=#000000 size=2>List&nbsp;cats&nbsp;=&nbsp;</font><font size=2><font color=#000000><strong>sess.createCriteria(Cat.class)<br>&nbsp;&nbsp;&nbsp;&nbsp;.createAlias("kittens",&nbsp;"kt")<br></strong>&nbsp;&nbsp;&nbsp;&nbsp;.createAlias("mate",&nbsp;"mt")<br>&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.eqProperty("kt.name",&nbsp;"mt.name")&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;.list();<br>（createAlias()）并不会创建一个Criteria的新实例。）&nbsp;</font></font></p>
<p><font color=#000000 size=2>请注意，前面两个查询中Cat实例所持有的kittens集合类并没有通过criteria预先过滤！如果你希望只返回满足条件的kittens,你必须使用returnMaps()。&nbsp;</font></p>
<p><font color=#000000 size=2>List&nbsp;cats&nbsp;=&nbsp;sess.createCriteria(Cat.class)<br>&nbsp;&nbsp;&nbsp;&nbsp;.createCriteria("kittens",&nbsp;"kt")<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.eq("name",&nbsp;"F%")&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;.returnMaps()<br>&nbsp;&nbsp;&nbsp;&nbsp;.list();<br>Iterator&nbsp;iter&nbsp;=&nbsp;cats.iterator();<br>while&nbsp;(&nbsp;iter.hasNext()&nbsp;)&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;Map&nbsp;map&nbsp;=&nbsp;(Map)&nbsp;iter.next();<br>&nbsp;&nbsp;&nbsp;&nbsp;Cat&nbsp;cat&nbsp;=&nbsp;(Cat)&nbsp;map.get(Criteria.ROOT_ALIAS);<br>&nbsp;&nbsp;&nbsp;&nbsp;Cat&nbsp;kitten&nbsp;=&nbsp;(Cat)&nbsp;map.get("kt");<br>}<br></font><font size=2><font color=#000000><strong>5、动态关联对象获取（Dynamic&nbsp;association&nbsp;fetching）<br></strong>可以在运行时通过setFetchMode()来改变关联对象自动获取的策略。&nbsp;</font></font></p>
<p><font color=#000000 size=2>List&nbsp;cats&nbsp;=&nbsp;sess.createCriteria(Cat.class)<br>&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Expression.like("name",&nbsp;"Fritz%")&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;.setFetchMode("mate",&nbsp;FetchMode.EAGER)<br>&nbsp;&nbsp;&nbsp;&nbsp;.list();<br>这个查询会通过外连接(outer&nbsp;join)同时获得&nbsp;mate和kittens。&nbsp;</font></p>
<p><font size=2><font color=#000000><strong>6、根据示例查询（Example&nbsp;queries）</strong><br>net.sf.hibernate.expression.Example类允许你从指定的实例创造查询条件。&nbsp;</font></font></p>
<p><font color=#000000 size=2>Cat&nbsp;cat&nbsp;=&nbsp;new&nbsp;Cat();<br>cat.setSex('F');<br>cat.setColor(Color.BLACK);<br>List&nbsp;results&nbsp;=&nbsp;session.createCriteria(Cat.class)<br>&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Example.create(cat)&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;.list();<br>版本属性，表示符属性和关联都会被忽略。默认情况下，null值的属性也被排除在外。&nbsp;</font></p>
<p><font color=#000000 size=2>You&nbsp;can&nbsp;adjust&nbsp;how&nbsp;the&nbsp;Example&nbsp;is&nbsp;applied.&nbsp;你可以调整示例(Example)如何应用。&nbsp;</font></p>
<p><font color=#000000 size=2>Example&nbsp;example&nbsp;=&nbsp;Example.create(cat)<br>&nbsp;&nbsp;&nbsp;&nbsp;.excludeZeroes()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//exclude&nbsp;zero&nbsp;valued&nbsp;properties<br>&nbsp;&nbsp;&nbsp;&nbsp;.excludeProperty("color")&nbsp;&nbsp;//exclude&nbsp;the&nbsp;property&nbsp;named&nbsp;"color"<br>&nbsp;&nbsp;&nbsp;&nbsp;.ignoreCase()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//perform&nbsp;case&nbsp;insensitive&nbsp;string&nbsp;comparisons<br>&nbsp;&nbsp;&nbsp;&nbsp;.enableLike();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//use&nbsp;like&nbsp;for&nbsp;string&nbsp;comparisons<br>List&nbsp;results&nbsp;=&nbsp;session.createCriteria(Cat.class)<br>&nbsp;&nbsp;&nbsp;&nbsp;.add(example)<br>&nbsp;&nbsp;&nbsp;&nbsp;.list();<br>你甚至可以用示例对关联对象建立criteria。&nbsp;</font></p>
<p><font color=#000000 size=2>List&nbsp;results&nbsp;=&nbsp;session.createCriteria(Cat.class)<br>&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Example.create(cat)&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;.createCriteria("mate")<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.add(&nbsp;Example.create(&nbsp;cat.getMate()&nbsp;)&nbsp;)<br>&nbsp;&nbsp;&nbsp;&nbsp;.list();<br></font></p>
</div>
<img src ="http://www.cnitblog.com/afa202/aggbug/43336.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/afa202/" target="_blank">火炏炎焱燚</a> 2008-05-05 11:23 <a href="http://www.cnitblog.com/afa202/archive/2008/05/05/43336.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>oracle语句</title><link>http://www.cnitblog.com/afa202/archive/2008/03/19/41173.html</link><dc:creator>火炏炎焱燚</dc:creator><author>火炏炎焱燚</author><pubDate>Wed, 19 Mar 2008 08:55:00 GMT</pubDate><guid>http://www.cnitblog.com/afa202/archive/2008/03/19/41173.html</guid><wfw:comment>http://www.cnitblog.com/afa202/comments/41173.html</wfw:comment><comments>http://www.cnitblog.com/afa202/archive/2008/03/19/41173.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/afa202/comments/commentRss/41173.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/afa202/services/trackbacks/41173.html</trackback:ping><description><![CDATA[&nbsp;
<p><span>Update base_ct set ct=null where id=1;</span></p>
<p>&nbsp;</p>
<p><span>Select address||&#8217;kong&#8217;|| &#8216; &#8217;||id &nbsp;from address;</span></p>
<p>&nbsp;</p>
<p><span>Select last_name aa from address;//</span><span>大写显示标题</span></p>
<p>&nbsp;</p>
<p><span>Select las_name AS &#8220;aa&#8221; from address;//</span><span>栏位保持不变</span><span> aa</span></p>
<p>&nbsp;</p>
<p><span>Like </span><span>区分大小写；</span></p>
<p>&nbsp;</p>
<p><span>Select * from t1 where id</span></p>
<p><span>Between 10 and 20&nbsp;and name &nbsp;is (not) null and id not in(10,20,5,6);</span></p>
<p>&nbsp;</p>
<p><span>Select lower(al_name ),upper(fname) from auther;</span></p>
<p>&nbsp;</p>
<p><span>Select concat(&#8216;hello&#8217;,name) from auther;//</span><span>连接诶</span></p>
<p>&nbsp;</p>
<p><span>Select substr(lname,1,5) from auther//</span><span>从第个截取</span><span>5</span><span>个；</span></p>
<p>&nbsp;</p>
<p><span>Instr(lname,&#8217;w&#8217;)</span><span>判断存在位置；</span><span> lpad</span><span>（</span><span>au_name,15,&#8217;&amp;&#8217;</span><span>）左填充</span><span>&amp;</span><span>到</span><span>15</span><span>位长度；</span></p>
<p>&nbsp;</p>
<p><span>Round</span><span>（</span><span>45.926</span><span>，</span><span>2</span><span>）求余，</span><span>trunc</span><span>（</span><span>45.923</span><span>，</span><span>2</span><span>）截取</span></p>
<p>&nbsp;</p>
<p><span>Nvl(name,&#8217;tom&#8217;)//</span><span>是否位空空，如实是就用后面的填充，否则返回原值。</span></p>
<p>&nbsp;</p>
<p><span>Nvl2</span><span>（</span><span>name</span><span>，&#8216;</span><span>have name</span><span>&#8217;</span><span>,&#8217;have not name&#8217;</span><span>）</span></p>
<p>&nbsp;</p>
<p><span>Nullif(name1,name2)</span><span>如果相等返回空，否贼返回第一个；</span></p>
<p>&nbsp;</p>
<p><span>Cocalesce</span><span>（，，，，）直到找到第一个不为空的值。</span></p>
<p>&nbsp;</p>
<p><span>Natural join aa;</span><span>依据</span><span>aa</span><span>同名的栏位连接；</span></p>
<p><span>Using</span><span>（</span><span>aa</span><span>，</span><span>bb</span><span>）依据多个栏位同名连接；</span></p>
<p>&nbsp;</p>
<p><span>Left outer join </span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span>Create view testview </span></p>
<p><span>As </span></p>
<p><span>Select stor_id,qty;</span></p>
<p>&nbsp;</p>
<p><span>Select * from testview;</span></p>
<p>&nbsp;</p>
<p><span>Select * from sales union select * from sales,</span><span>集合操作；排序，删除重复</span></p>
<p><span>Select * from sales1 union all select * from sales2 </span><span>不删除重复，不排序</span></p>
<p>&nbsp;</p>
<p><span>Select * from sales1 intersect all select * from sales2</span><span>求交集</span></p>
<p>&nbsp;</p>
<p><span>Select * from sales1 minus all select * from sales2</span><span>第一句减去交集；</span></p>
<p>&nbsp;</p>
<p><span>Insert all </span></p>
<p><span>When name like &#8216;b%&#8217; then into t1,</span></p>
<p><span>When name like &#8216;c%&#8217; then into t2,</span></p>
<p><span>Select * from sales;</span></p>
<img src ="http://www.cnitblog.com/afa202/aggbug/41173.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/afa202/" target="_blank">火炏炎焱燚</a> 2008-03-19 16:55 <a href="http://www.cnitblog.com/afa202/archive/2008/03/19/41173.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>打印</title><link>http://www.cnitblog.com/afa202/archive/2007/11/01/35687.html</link><dc:creator>火炏炎焱燚</dc:creator><author>火炏炎焱燚</author><pubDate>Thu, 01 Nov 2007 02:13:00 GMT</pubDate><guid>http://www.cnitblog.com/afa202/archive/2007/11/01/35687.html</guid><wfw:comment>http://www.cnitblog.com/afa202/comments/35687.html</wfw:comment><comments>http://www.cnitblog.com/afa202/archive/2007/11/01/35687.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/afa202/comments/commentRss/35687.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/afa202/services/trackbacks/35687.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 先给一个简单实用的方式（可以打印多页，控制分页，隐藏非打印项目）&lt;!--语言无关&nbsp;保存成&nbsp;.HTML&nbsp;看看--&gt;&nbsp;&lt;html&gt;&nbsp;&lt;head&gt;&nbsp;&lt;meta&nbsp;name=vs_targetSchema&nbsp;content="http://schemas.microsoft.com...&nbsp;&nbsp;<a href='http://www.cnitblog.com/afa202/archive/2007/11/01/35687.html'>阅读全文</a><img src ="http://www.cnitblog.com/afa202/aggbug/35687.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/afa202/" target="_blank">火炏炎焱燚</a> 2007-11-01 10:13 <a href="http://www.cnitblog.com/afa202/archive/2007/11/01/35687.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>socket </title><link>http://www.cnitblog.com/afa202/archive/2007/10/27/35459.html</link><dc:creator>火炏炎焱燚</dc:creator><author>火炏炎焱燚</author><pubDate>Sat, 27 Oct 2007 06:34:00 GMT</pubDate><guid>http://www.cnitblog.com/afa202/archive/2007/10/27/35459.html</guid><wfw:comment>http://www.cnitblog.com/afa202/comments/35459.html</wfw:comment><comments>http://www.cnitblog.com/afa202/archive/2007/10/27/35459.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/afa202/comments/commentRss/35459.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/afa202/services/trackbacks/35459.html</trackback:ping><description><![CDATA[<p>&nbsp; System.IO.FileStream file = new FileStream("c:/a.txt",System.IO.FileMode.OpenOrCreate);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte [] msg= new byte[file.Length];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; file.Read(msg, 0, msg.Length );</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Net.Sockets.Socket send = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork,System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Net.IPEndPoint ipendp = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("127.0.0.1"), 9999);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; send.Connect(ipendp);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; send.Send(msg);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; send.Shutdown(System.Net.Sockets.SocketShutdown.Both);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; send.Close();<br>//发送端<br><br>&nbsp;System.IO.FileStream file = new FileStream("c:/b.txt", System.IO.FileMode.OpenOrCreate);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Net.Sockets.Socket soclip = new System.Net.Sockets.Socket(System.Net.Sockets.AddressFamily.InterNetwork,<br>&nbsp;System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Net.IPEndPoint ipendp = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("127.0.0.1"), 9999);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; soclip.Bind(ipendp);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; soclip.Listen(100);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Net.Sockets.Socket soclipapp = soclip.Accept();</p>
<p>&nbsp;</p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] by = new byte[200];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string str = "";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; soclipapp.Receive(by);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; file.Write(by, 0, by.Length);//'将数据写到kk.txt中<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; file.Close();//'流关</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str = System.Text.Encoding.UTF8.GetString(by);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; soclipapp.Shutdown(System.Net.Sockets.SocketShutdown.Both);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; soclipapp.Close();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Write(str); <br>//接受，<br>//网上搜索，自己整理而来，名字我网了。在此表示谢谢<br>//运行此代码，建立两个工程。同时运行。这两个项目</p>
<img src ="http://www.cnitblog.com/afa202/aggbug/35459.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/afa202/" target="_blank">火炏炎焱燚</a> 2007-10-27 14:34 <a href="http://www.cnitblog.com/afa202/archive/2007/10/27/35459.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>commandname</title><link>http://www.cnitblog.com/afa202/archive/2007/10/03/34333.html</link><dc:creator>火炏炎焱燚</dc:creator><author>火炏炎焱燚</author><pubDate>Wed, 03 Oct 2007 07:02:00 GMT</pubDate><guid>http://www.cnitblog.com/afa202/archive/2007/10/03/34333.html</guid><wfw:comment>http://www.cnitblog.com/afa202/comments/34333.html</wfw:comment><comments>http://www.cnitblog.com/afa202/archive/2007/10/03/34333.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/afa202/comments/commentRss/34333.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/afa202/services/trackbacks/34333.html</trackback:ping><description><![CDATA[&nbsp;&lt;ItemTemplate&gt;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;asp:Button ID="asda" runat="server" Text="删除" CommandName="edit" /&gt;<br>&nbsp;&nbsp; delete&nbsp; edit,update,canlce<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/ItemTemplate&gt;
<img src ="http://www.cnitblog.com/afa202/aggbug/34333.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/afa202/" target="_blank">火炏炎焱燚</a> 2007-10-03 15:02 <a href="http://www.cnitblog.com/afa202/archive/2007/10/03/34333.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>