[Flex]Flex与.NET互操作(四):使用HttpService、URLReqeust和URL

mikel阅读(560)

   在前两篇文章中分别介绍了Flex与.NET的WebService之间的数据交互通信知识,本文将介绍另外一种加载数据以及发起请求的方 式。ActionScript 3.0中提供的数据加载请求类主要是HTTPService,URLLoader和URLRequest,可以通过他们协同来完成数据加载和请求。下面我 么便来看看这三个类是怎么来完成数据加载工作。

     在本地IIS服务器上有如下定义的XML文件:

 1 <?xml version="1.0" encoding="utf-8" ?>
 2 <Root>
 3   <Book>
 4     <Id>1</Id>
 5     <Name>《三国演义》</Name>
 6     <Author>罗贯中</Author>
 7     <Price>52.30</Price>
 8   </Book>
 9   <Book>
10     <Id>2</Id>
11     <Name>《西游记》</Name>
12     <Author>吴承恩</Author>
13     <Price>39.91</Price>
14   </Book>
15   <Book>
16     <Id>3</Id>
17     <Name>《红楼梦》</Name>
18     <Author>曹雪芹</Author>
19     <Price>48.20</Price>
20   </Book>
21   <Book>
22     <Id>4</Id>
23     <Name>《水浒传》</Name>
24     <Author>施耐庵</Author>
25     <Price>39.85</Price>
26   </Book>
27 </Root>

一、使用HTTPService传递和加载数据

     使用HTTPService可以实现加载数据,也可以实现参数传递,下面通过两个示例程序来讲解这两个知识点。

     首先来看看HTTPService加载数据的方式。在Flex中使用HTTPService来装载外部数据是非常简单的,他是基于 HTTP协议发送POST和GET请求外部数据,然后通过指定的监听方法来处理响应。我们可以通过<mx:HTTPService>标签来完 成对数据源的连接,也可以通过可编程方式来处理,两种方式没什么大的差距,实际开发中可以根据自己喜好选择。

 1 internal function onClick():void
 2 {
 3     var service:HTTPService = new HTTPService();
 4     service.url = "http://localhost:1146/Data/Book.xml";
 5     service.useProxy = false;
 6     service.resultFormat="e4x";
 7     service.addEventListener(ResultEvent.RESULT,onResultHandler);
 8     service.send();
 9 }
10 
11 internal function onResultHandler(evt:ResultEvent):void
12 {
13     var xml:XML = evt.result as XML;
14     trace(xml);
15     bookGrid.dataProvider = xml.Book;
16 }

 

     该示例的运行结果见文章最后,下面是这个示例的完整代码:

完整示例代码

 

     OK,我们来看看使用HTTPService传递参数到服务端是怎么实现的。使用HTTPService传递参数可以通过两种方式实现,分别如下:

     1、直接在请求URL后面跟上参数列表,如:http://localhost/web/Test.aspx?a=1&b=2

     2、通过Flex SDK为我们提供专门用语参数传递的对象(URLVariables)来实现。

     下面以一道简单的加法运算来演示HTTPService传递参数的使用,在Flex里将需要进行加法运算的两个数传递到.NET服务端并计算其和后返回给Flex客户端,两种方式传递没有太大的区别,详细请看如下代码演示:

 1 /**
 2  * 通过RUL参数直接传递
 3  * */
 4 internal function onClick():void
 5 {
 6     var service:HTTPService = new HTTPService();
 7     var a:String = txtA.text;
 8     var b:String = txtB.text;
 9     service.url = "http://localhost:1146/OperationHandler.ashx?a="+a+"&b="+b;
10     service.useProxy = false;
11     service.resultFormat="e4x";
12     service.addEventListener(ResultEvent.RESULT,onResultHandler);
13     service.send();
14 }
15 
16 /**
17  * 通过URLVariables进行参数传递
18  * */
19 internal function onClick():void
20 {
21     var service:HTTPService = new HTTPService();
22     service.url = "http://localhost:1146/OperationHandler.ashx";
23     service.useProxy = false;
24     service.resultFormat="e4x";
25     service.addEventListener(ResultEvent.RESULT,onResultHandler);
26     var param:URLVariables = new URLVariables();
27     param.a = txtA.text;
28     param.b = txtB.text;
29     service.send();
30 }

 

      下面是完整的示例代码,可以把onClick()方法相互切换来测试两种不同的参数传递方式。

完整的示例代码

 

OperationHandler.ashx

 

     上面示例的运行界面截图:

          


 

二、了解URLReqeust

     使用URLRequest 类可捕获单个 HTTP 请求中的所有信息。将URLRequest 对象传递给URLStream或URLLoader 类以及其他加载操作的load()方法以启动URL数据加载。它的使用很简单,通过构造方法构造对象就OK:

1 var request:URLRequest = new URLRequest("http://localhost:1146/Data/Book.xml")

 

     同样可以使用URLRequest来请求一个本地项目/应用里的文件,如下代码示例:

1 var request:URLRequest = new URLRequest("Data/Book.xml")

 
     如上便构造好了URLRequest对象,只要将他传递给相应的对象load()方法便可实现数据加载。从某种角度可以将URLRequest 理解为建立请求的工具。要是URLRequest类对象变成可用的对象还需得通过其他类来与之配合协作,详细见后面使用URLLoader加载数据。

     URLRequest虽然功能强大,使用简单。但我们还是需要了解更多的东西,以便可以正确的应用URLRequest类和处理相应的错误。其中最引人关注的就是安全沙箱的问题,这部分我将在以后的文章中介绍,这里只需要记住两点就OK。  

     1、如果执行调用的 SWF 文件在只能与本地文件系统内容交互的沙箱中,而目标资源来自网络沙箱,则不允许进行数据加载。

     2、如果执行调用的 SWF 文件来自网络沙箱而目标资源在本地,也不允许进行数据加载。

     这里就简单介绍这些,关于URLRequest的详细资料大家可以查看官方提供的在线文档:http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/net/URLRequest.html


 

三、使用URLLoader加载数据

     URLLoader 类可以以文本、二进制数据或 URL 编码变量的形式从 URL 下载数据。下面将结合使用本地服务器上的数据(详细见文章前面的xml文件定义)的加载示例来演示URLLoader的使用方法。 

      那我们怎么通过URLLoader来加载它呢?很简单,使用上面介绍的URLRequest来创建请求连接,然后将URLRequest对象传递给URLLoader的load方法来实现数据加载。

 1 internal function onClick():void
 2 {
 3     var request:URLRequest = new URLRequest("http://localhost:1146/Data/Book.xml");
 4     var loader:URLLoader = new URLLoader();
 5     loader.load(request);
 6     loader.addEventListener(Event.COMPLETE,onCompleteHandler);
 7 }
 8 
 9 private function onCompleteHandler(evt:Event):void
10 {
11     var xml:XML = new XML(evt.target.data);
12     bookGrid.dataProvider = xml.Book;
13 }

     下面是整个mxml的代码定义:


 1 <?xml version="1.0" encoding="utf-8"?>
 2 <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
 3     <mx:Script>
 4         <![CDATA[
 5             internal function onClick():void
 6             {
 7                 var request:URLRequest = new URLRequest("http://localhost:1146/Data/Book.xml");
 8                 var loader:URLLoader = new URLLoader();
 9                 loader.load(request);
10                 loader.addEventListener(Event.COMPLETE,onCompleteHandler);
11             }
12             
13             private function onCompleteHandler(evt:Event):void
14             {
15                 var xml:XML = new XML(evt.target.data);
16                 bookGrid.dataProvider = xml.Book;
17             }
18         ]]>
19     </mx:Script>
20     <mx:Panel x="49.5" y="94" width="419" height="267" layout="absolute" fontSize="12" borderColor="#E2E2E2" themeColor="#009DDF" title="使用URLLoader加在XML数据">
21         <mx:DataGrid x="10" y="10" width="377" id="bookGrid">
22             <mx:columns>
23                 <mx:DataGridColumn headerText="编号" dataField="Id"/>
24                 <mx:DataGridColumn headerText="书名" dataField="Name"/>
25                 <mx:DataGridColumn headerText="作者" dataField="Author"/>
26                 <mx:DataGridColumn headerText="价格" dataField="Price"/>
27             </mx:columns>
28         </mx:DataGrid>
29         <mx:ControlBar height="42">
30             <mx:Button label="加载数据" fontWeight="normal" click="onClick()"/>
31         </mx:ControlBar>
32     </mx:Panel>
33 </mx:Application>
34 

 

     本示例的运行结果如下图:

       

 

关于URLLoader的更多资料大家可以查看Adobe提供的在线文档:http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/net/URLLoader.html

 

版权说明

  本文属原创文章,欢迎转载,其版权归作者和博客园共有。  

  作      者:Beniao

 文章出处:http://beniao.cnblogs.com/  或  http://www.cnblogs.com/

 

[MVC]Asp.net MVC :Custom Action Filters

mikel阅读(825)

来自:http://quickstarts.ASP.NET/previews/mvc/mvc_ActionFiltering.htm

Custom Action Filters

Introduction

The possible uses for action filters are as varied as the actions to which they can be applied. Some possible uses for action filters include the following:

  • Logging to track user interactions.
  • "Anti-image-leeching" to prevent images from being loaded in pages that are not on your site.
  • Web crawler filtering to change application behavior based on the browser user agent.
  • Localization to set the locale.
  • Dynamic actions to inject an action into a controller.

Implementing a Custom Action Filter

An action filter is implemented as an attribute class that inherits from ActionFilterAttribute. ActionFilterAttribute is an abstract class that has four virtual methods that you can override: OnActionExecuting, OnActionExecuted, OnResultExecuting, and OnResultExecuted. You must override at least one of these methods.
The ASP.NET MVC framework will call the OnActionExecuting method of your action filter before it calls any action method that is marked with your action filter attribute. Similarly, the framework will call the OnActionExecuted method after the action method has finished.
The OnResultExecuting method is called just before the ActionResult instance that is returned by your action is invoked. The OnResultExecuted method is called just after the result is executed. These methods are useful for performing actions such as logging, output caching, and so forth.
The following example shows a simple action filter that logs trace messages before and after an action method is called.

Visual Basic

Public Class LoggingFilterAttribute
Inherits ActionFilterAttribute
Public Overrides Sub OnActionExecuting(ByVal filterContext _
As ActionExecutingContext)
filterContext.HttpContext.Trace.Write("Starting: " & _
filterContext.ActionMethod.Name)
MyBase.OnActionExecuting(filterContext)
End Sub
Public Overrides Sub OnActionExecuted(ByVal filterContext _
As ActionExecutedContext)
If Not filterContext.Exception Is Nothing Then
filterContext.HttpContext.Trace.Write("Exception thrown")
End If
MyBase.OnActionExecuted(filterContext)
End Sub
End Class

public class LoggingFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext
filterContext)
{
filterContext.HttpContext.Trace.Write("Starting: " +
filterContext.ActionMethod.Name);
base.OnActionExecuting(filterContext);
}
public override void OnActionExecuted(ActionExecutedContext
filterContext)
{
if (filterContext.Exception != null)
filterContext.HttpContext.Trace.Write("Exception thrown");
base.OnActionExecuted(filterContext);
}
}

Action Filter Context

Each of the controller event handlers for action filtering takes a context object as a parameter. The following list shows the event handlers and the context type that each takes.

  • OnActionExecuting takes an ActionExecutingContext object.
  • OnActionExecuted takes an ActionExecutedContext object.
  • OnResultExecuting takes a ResultExecutingContext object.
  • OnResultExecuted takes a ResultExecutedContext object.

All context classes inherit from the ControllerContext class and include an ActionMethod property. You can use the ActionMethod property to identify which action the filter is currently applied to.
The ActionExecutingContext and ResultExecutingContext classes contain a Cancel property that enables you to cancel the action.
The ActionExecutedContent and ResultExecutedContext classes contain an Exception property and an ExceptionHandled property. If the Exception property is null, it indicates that no error occurred when the action method ran. If the Exception property is not null and the filter knows how to handle the exception, the filter can handle the exception and then signal that it has done so by setting the ExceptionHandled property to true. Even if the ExceptionHandled property is true, the OnActionExecuted or OnResultExecuted method of any additional action filters in the stack will be called and exception information will be passed to them. This enables scenarios such as letting a logging filter log an exception even though the exception has been handled. In general, an action filter should not handle an exception unless the error is specific to that filter.

Marking an Action Method with a Filter Attribute

You can apply an action filter to as many action methods as you need. The following example shows a controller that contains action methods that are marked with an action-filter attribute. In this case, all the action methods in the controller will invoke the same action filter.

Visual Basic

Public Class HomeController
Inherits Controller
Shared clicked As Boolean = False
<LoggingFilter()> _
Public Function Index()
ViewData("Title") = "Home Page"
ViewData("Message") = "Welcome to ASP.NET MVC!"
If clicked = True Then
ViewData("Click") = "You clicked this button."
clicked = False
End If
Return View()
End Function
<LoggingFilter()> _
Public Function About()
ViewData("Title") = "About Page"
Return View()
End Function
<LoggingFilter()> _
Public Function ClickMe()
clicked = True
Return RedirectToAction("Index")
End Function
End Class

public class HomeController : Controller
{
static Boolean clicked = false;
[LoggingFilter]
public ActionResult Index()
{
ViewData["Title"] = "Home Page";
ViewData["Message"] = "Welcome to ASP.NET MVC!";
if (clicked == true)
{
ViewData["Click"] = "You clicked this button.";
clicked = false;
}
return View();
}
[LoggingFilter]
public ActionResult About()
{
ViewData["Title"] = "About Page";
return View();
}
[LoggingFilter]
public ActionResult ClickMe()
{
clicked = true;
return RedirectToAction("Index");
}
}
Note:
If you want to apply an action filter to all action methods of a controller, you can mark the controller with the filter attribute. This is the same as marking every action method with the attribute.

Executing Code Before and After an Action from Within a Controller

The ASP.NET MVC Controller class defines OnActionExecuting and OnActionExecuted methods that you can override. When you override one or both of these methods, your logic will execute before or after all action methods of that controller. This functionality is like action filters, but the methods are controller-scoped.
The following example shows controller-level OnActionExecuting and OnActionExecuted methods that apply to all action methods in the controller.

Visual Basic

Public Class HomeController
Inherits Controller
Shared clicked As Boolean = False
Public Function Index()
ViewData("Title") = "Home Page"
ViewData("Message") = "Welcome to ASP.NET MVC!"
If clicked = True Then
ViewData("Click") = "You clicked this button."
clicked = False
End If
Return View()
End Function
Public Function About()
ViewData("Title") = "About Page"
Return View()
End Function
Public Function ClickMe()
clicked = True
Return RedirectToAction("Index")
End Function
Protected Overrides Sub OnActionExecuting(ByVal filterContext _
As ActionExecutingContext)
filterContext.HttpContext.Trace.Write("Action Executing: " & _
filterContext.ActionMethod.Name)
If clicked = True Then
filterContext.HttpContext.Trace.Write("Button clickced")
End If
MyBase.OnActionExecuting(filterContext)
End Sub
Protected Overrides Sub OnActionExecuted(ByVal filterContext _
As ActionExecutedContext)
If Not filterContext.Exception Is Nothing Then
filterContext.HttpContext.Trace.Write("Exception thrown")
End If
MyBase.OnActionExecuted(filterContext)
End Sub
End Class

public class HomeController : Controller
{
static Boolean clicked = false;
public ActionResult Index()
{
ViewData["Title"] = "Home Page";
ViewData["Message"] = "Welcome to ASP.NET MVC!";
if (clicked == true)
{
ViewData["Click"] = "You clicked this button.";
clicked = false;
}
return View();
}
public ActionResult About()
{
ViewData["Title"] = "About Page";
return View();
}
public ActionResult ClickMe()
{
clicked = true;
return RedirectToAction("Index");
}
protected override void OnActionExecuting(ActionExecutingContext
filterContext)
{
filterContext.HttpContext.Trace.Write("Action Executing: " +
filterContext.ActionMethod.Name);
if (clicked == true)
filterContext.HttpContext.Trace.Write("Button clickced");
base.OnActionExecuting(filterContext);
}
protected override void OnActionExecuted(ActionExecutedContext
filterContext)
{
if (filterContext.Exception != null)
filterContext.HttpContext.Trace.Write("Exception thrown");
base.OnActionExecuted(filterContext);
}
}

Scope of Action Filters

In addition to marking individual action methods with an action filter, you can mark a controller class as a whole with an action filter. In that case, the filter applies to all action methods of that controller.
Additionally, if your controller derives from another controller, the base controller might have its own action-filter attributes. Likewise, if your controller overrides an action method from a base controller, the method might have its own action-filter attributes and those it inherits from the overridden action method.
To make it easier to understand how action filters work together, action methods are grouped into scopes. A scope defines where the attribute applies, such as whether it marks a class or a method, and whether it marks a base class or a derived class.

Order of Execution for Action Filters

Each action filter has an Order property, which is used to determine the order that filters are executed in the scope of the filter. The Order property takes an integer value that must be 0 (default) or greater (with one exception). Omitting the Order property gives the filter an order value of -1, which indicates an unspecified order. Any action filters in a scope whose Order property is set to -1 will be executed in a nondeterministic order, but before the filters that have a specified order.
When an Order property of a filter is specified, it must be set to a unique value in a scope. If two or more action filters in a scope have the same Order property value, an exception is thrown.
Action filters are executed in an order that meets the following constraints. If more than one ordering fulfills all these constraints, the selected ordering is undetermined.
1. The implementation of the OnActionExecuting and OnActionExecuted methods on the controller always go first. For more information, see Executing Code Before and After an Action from Within a Controller.
2. Unless the Order property explicitly set, an action filter has an implied order of -1.
3. If the order property of multiple action filters are explicitely set, the one with the lowest value executes before those with greater values, as shown in the following example.

Visual Basic

<Filter1(Order = 2)> _
<Filter2(Order = 3)> _
<Filter3(Order = 1)> _
Public Sub Index()
View("Index")
End Sub
C#

[Filter1(Order = 2)]
[Filter2(Order = 3)]
[Filter3(Order = 1)]
public void Index()
{
View("Index");
}
In this example, action filters would execute in the following order: Filter3, Filter1, and then Filter2.

4. If two action filters have the same Order property value, and if one action filter is defined on a type and the other action filter is defined on a method, the action filter defined on the type executes first.

Visual Basic

<FilterType(Order = 1)> _
Public Class MyController
<FilterMethod(Order = 1)> _
Public  Sub Index()
View("Index")
End Sub
End Class
C#

[FilterType(Order = 1)]
public class MyController
{
[FilterMethod(Order = 1)]
public void Index()
{
View("Index");
}
}

In this example, FilterType executes before FilterMethod.

Example of Action Filter order of Execution

The following example shows an MVC application that contains two action filters. The DebugFilter filter writes trace messages, and the ThrowExceptionFilter filter causes an exception. The application also contains a base controller, a derived controller, and a view.
The following example shows the class that defines the DebugFilter filter. The filter uses some static methods and properties to trace filter depth and to control indentation of the output.

C#

public class DebugFilterAttribute : ActionFilterAttribute
{
public static void Reset()
{
counter = 1;
indent = 0;
incrementIndex = true;
}
public static int Counter
{
get
{
return counter++;
}
}
static int counter
{
get
{
return (int)(HttpContext.Current.Items["counter"] ?? 1);
}
set
{
HttpContext.Current.Items["counter"] = value;
}
}
static int indent
{
get
{
return (int)(HttpContext.Current.Items["indent"] ?? 1);
}
set
{
HttpContext.Current.Items["indent"] = value;
}
}
static bool incrementIndex
{
get
{
return (bool)(HttpContext.Current.Items["incrementIndex"] ?? true);
}
set
{
HttpContext.Current.Items["incrementIndex"] = value;
}
}
public string Message { get; set; }
public int Id { get; set; }
public override void OnActionExecuting(ActionExecutingContext
filterContext)
{
HttpContext.Current.Trace.Write(
"Action Filter",
string.Format("{0}: {3}(PRE) DebugFilter.OnActionExecuting - order={1} Message='{2}'",
Counter,
this.Order,
this.Message,
Indent)
);
}
public override void OnActionExecuted(ActionExecutedContext
filterContext)
{
HttpContext.Current.Trace.Write(
"Action Filter",
string.Format("{0}: {3}(POST) DebugFilter.OnActionExecuted - order={1} Message='{2}'",
Counter,
this.Order,
this.Message,
Indent)
);
}
public static string Indent
{
get
{
indent += (incrementIndex ? 1 : -1);
string indentText = string.Empty;
for (int i = 0; i < indent; i++)
indentText += " ";
return indentText;
}
}
public static void StartDecrement()
{
incrementIndex = false;
}
}

The following example shows a class that defines the base controller with action filters applied.

C#

[DebugFilter(Message = "(CONTROLLER) MyBaseController", order = 1)]
[DebugFilter(Message = "(CONTROLLER) MyBaseController", order=2)]
public class MyBaseController : Controller
{
[DebugFilter(Message = "(ACTION) MyBaseController.Index()", order=2)]
[DebugFilter(Message = "(ACTION) MyBaseController.Index()", order=1)]
public virtual ActionResult Index()
{
return View();
}
}

The following example shows a class that defines the derived controller with action filters applied. Notice that this controller implements its OnActionExecuting and OnActionExecuted methods.

C#

[DebugFilter(Message = "(CONTROLLER) MyDerivedController", order = 2)]
[DebugFilter(Message = "(CONTROLLER) MyDerivedController", order=1)]
public class MyDerivedController : MyBaseController
{
[DebugFilter(Message = "(ACTION) MyDerivedController.Index()", order=1)]
[DebugFilter(Message = "(ACTION) MyDerivedController.Index()", order = 2)]
// Uncomment the following line to cause an exception to be
// thrown and to see what happens in the trace messages.
//[ThrowExceptionFilter(Message = "(ACTION) Exception thrown!", order=3)]
public override ActionResult Index()
{
base.Index();
HttpContext.Trace.Write("Action Filter",
string.Format("{0}: {1}(ACTION) MyDerivedController.Index()",
DebugFilterAttribute.Counter,
DebugFilterAttribute.Indent));
DebugFilterAttribute.StartDecrement();
return View();
}
protected override void OnActionExecuting(ActionExecutingContext
filterContext)
{
// Processing begins here.
DebugFilterAttribute.Reset();
HttpContext.Trace.Write("Action Filter",
string.Format("{0}: {1}(PRE) MyDerviedController.OnActionExecuting VIRTUAL METHOD",
DebugFilterAttribute.Counter,
DebugFilterAttribute.Indent));
}
protected override void OnActionExecuted(ActionExecutedContext
filterContext)
{
HttpContext.Trace.Write("Action Filter",
string.Format("{0}: {1}(POST) MyDerviedController.OnActionExecuted VIRTUAL METHOD",
DebugFilterAttribute.Counter,
DebugFilterAttribute.Indent));
if (filterContext.Exception != null)
filterContext.ExceptionHandled = true;
// Processing ends here.
((MyDerivedController)filterContext.Controller).View("Index");
}
}

The following example shows the Index view for the application whose Trace property is set to true.

HTML

<%@ Page Language="C#" CodeBehind="Index.aspx.cs"
Inherits="ActionFilterTests.Views.MyDerived.Index" Trace="true" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Attribute Filter Test</title>
</head>
<body>
<form id="form1" runat="server">
<div>
Hello World
</div>
</form>
</body>
</html>

The following example shows the output trace messages that are displayed when this application runs.

(PRE) MyDerviedController.OnActionExecuting VIRTUAL METHOD
(PRE) DebugFilter.OnActionExecuting - order=1 Message='(CONTROLLER) MyBaseController
(PRE) DebugFilter.OnActionExecuting - order=2 Message='(CONTROLLER) MyBaseController
(PRE) DebugFilter.OnActionExecuting - order=1 Message='(CONTROLLER) MyDerivedController
(PRE) DebugFilter.OnActionExecuting - order=2 Message='(CONTROLLER) MyDerivedController
(PRE) DebugFilter.OnActionExecuting - order=1 Message='(ACTION) MyBaseController.Index()
(PRE) DebugFilter.OnActionExecuting - order=2 Message='(ACTION) MyBaseController.Index()
(PRE) DebugFilter.OnActionExecuting - order=1 Message='(ACTION) MyDerivedController.Index()
(PRE) DebugFilter.OnActionExecuting - order=2 Message='(ACTION) MyDerivedController.Index()
(ACTION) MyDerivedController.Index() 0.010142769541939 0.008739
(POST) DebugFilter.OnActionExecuted - order=2 Message='(ACTION) MyDerivedController.Index()
(POST) DebugFilter.OnActionExecuted - order=1 Message='(ACTION) MyDerivedController.Index()
(POST) DebugFilter.OnActionExecuted - order=2 Message='(ACTION) MyBaseController.Index()
(POST) DebugFilter.OnActionExecuted - order=1 Message='(ACTION) MyBaseController.Index()
(POST) DebugFilter.OnActionExecuted - order=2 Message='(CONTROLLER) MyDerivedController
(POST) DebugFilter.OnActionExecuted - order=1 Message='(CONTROLLER) MyDerivedController
(POST) DebugFilter.OnActionExecuted - order=2 Message='(CONTROLLER) MyBaseController
(POST) DebugFilter.OnActionExecuted - order=1 Message='(CONTROLLER) MyBaseController
(POST) MyDerviedController.OnActionExecuted VIRTUAL METHOD

See Also

Controllers and Controller Actions
ASP.NET Model View Controller Applications
How to: Create an Action Filter in Visual Studio

[MVC]ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第六篇:拦截器

mikel阅读(665)

摘要
      本文将对“MVC公告发布系统”的发布公告功能添加日志功能和异常处理功能,借此来讨论ASP.NET MVC中拦截器的使用方法。
一个小难题
      我们继续完善“MVC公告发布系统”,这次,我们的需求是对公告发布功能添加日志记录能力,即在发布公告前,记录一次,在公告发布成功后,再记录一次。然后还要使得其具备异常处理,即当业务组件出现问题时,跳转到相应的错误页面并显示相应提示。
      有人可能笑了,这有什么难的,在DoRelease这个Action的开始和结束处各加入相应日志功能不久结了。异常处理更不在话下,直接try…catch搞定。
      没错,以上方法确实行得通,但是存在以下两点问题:
      1.代码重复问题。很多日志处理代码和异常处理代码是很相似的,这样就导致了各个Action中存在大量重复代码。
      2.职责被破坏。不要忘了,我们的Controller仅仅是控制器,它应该只负责表示逻辑,而不应该被一大堆日志处理代码和try…catch块包围。我们要的Action,应该是干净的、工整的、仅包含表示逻辑的Action。
      以上两点,造成了我们系统中的坏味代码。那么,怎么解决这个问题呢?
从厨师到AOP
      先来想象一个场景:饭店里的高级厨师怎么工作?我们知道,他不用洗菜切菜、不用端着盘子送菜、如果发现手里牛肉变质了他更不用拿着牛肉去找肉店老板理论,他的工作很单一:炒菜。
      当原料送来后,有专门的顺菜切菜工进行洗菜、切菜,然后把处理好的菜送给厨师,厨师只管下锅炒,炒完了送菜自然也不必关心,因为有专门的服务员负责这事。如果发现牛肉变质了,它只管说一声,自然有相应的人处理这事。
      这个场景就是典型的AOP(面向切面编程)。厨师可以看成是业务组件,它有个方法就是“炒菜”,但是炒菜前要切菜,炒完了要有人送菜,可这不是厨师该关心 的事啊!于是我们的切菜工和服务员就相当于拦截器,其中切菜工在炒菜前拦截,进行切菜,服务员在炒菜后拦截,负责送菜。当然,我们还有个异常拦截器:处理 问题的人,就是那个当厨师发现肉变质了喊一声,就来处理的人。
      基于这个场景,我们看看这样有什么好处。首先是厨师职责单一了,他可以专注于自己的工作:炒菜,而不必理会不该自己关心的问题。而且“拦截器们”可以复用 的,例如一个抠门的老板完全可以找3个厨师但是只招一名服务员,反正一名服务员就可以给三名厨师端菜,这样,拦截器的复用使得代码重复不见了!
回来
      好的,现在回到我们的“MVC公告发布系统”。相信看了上面的场景,你的灵感一定来了:对啊,Action不就是厨师吗,如果我们可以将日志功能做成拦截 器,在DoRelease执行前先拦截一次完成记录日志功能,DoRelease执行后再拦截一次记录一次日志。最好还有个拦截器,在Action发生异 常的时候可以拦截处理(就像上文处理变质牛肉的人),不就搞定了吗。
      可是要怎么实现拦截Action呢?真是幸运之极,ASP.NET MVC框架中内置了这种机制!哈哈,我们赶快来做吧!
实现拦截器
      在ASP.NET MVC中,有三种拦截器:Action拦截器、Result拦截器和Exception拦截器。我要用到第一种和第三种。其实所谓的ASP.NET MVC拦截器,也没什么神秘的,就是一个普通的类而已。只不过需要继承FilterAttribute基类,Action拦截器还要实现IActionFilter接口,而Exception拦截器需要实现IExceptionFilter接口。
      我们先来看实现:让我们在Controllers目录下新建一个Filters目录,然后在Filters下新建两个类,一个叫LoggerFilter一个叫ExceptionFilter。首先是LoggerFilter的代码。
LoggerFilter.cs:

 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Web;
 5using System.Web.Mvc;
 6using System.Web.Mvc.Ajax;
 7
 8namespace MVCDemo.Controllers.Filters
 9{
10    public class LoggerFilter : FilterAttribute, IActionFilter
11    {
12        void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
13        {
14            filterContext.Controller.ViewData["ExecutingLogger"= "正要添加公告,已以写入日志!时间:" + DateTime.Now; 
15        }

16
17        void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext)
18        {
19            filterContext.Controller.ViewData["ExecutedLogger"= "公告添加完成,已以写入日志!时间:" + DateTime.Now;
20        }

21    }

22}


      可以看到,这个类继承了FilterAttribute并实现了IActionFilter。其中关键是IActionFilter,它有两个方 法,OnActionExecuting在被拦截Action前执行,OnActionExecuted在被拦截Action后执行。两个方法都有一个参 数,虽然类型不同,但其实都是一个作用:被拦截Action的上下文。
      这个地方我得解释一下,你拦截器拦截了Action,在做处理时难免要用到被拦截Action相关的东西,例如在我们的例子中,就需要想被拦截 Action所在Controller的ViewData中添加内容,所以,拦截器方法有一个参数表示被拦截Action的上下文是顺理成章的事。
      下面再看ExceptionFilter这个拦截器,它是在Action出现异常时发挥作用的。
ExceptionFilter.cs:

 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Web;
 5using System.Web.Mvc;
 6using System.Web.Mvc.Ajax;
 7
 8namespace MVCDemo.Controllers.Filters
 9{
10    public class ExceptionFilter : FilterAttribute,IExceptionFilter
11    {
12        void IExceptionFilter.OnException(ExceptionContext filterContext)
13        {
14            filterContext.Controller.ViewData["ErrorMessage"= filterContext.Exception.Message;
15            filterContext.Result = new ViewResult()
16            {
17                ViewName = "Error",
18                ViewData = filterContext.Controller.ViewData,
19            }
;
20            filterContext.ExceptionHandled = true;
21        }

22    }

23}


      异常拦截器一样需要继承FilterAttribute,但是不要实现IActionFilter,而是要实现IExceptionFilter接口,这 个接口只有一个方法:OnException,顾名思义,当然是发生异常时被调用了。我们看看我让它做了什么:首先将异常信息 (ExceptionContext一样也是上下文,而其成员的Exception就是一个Exception类型的实例,就是被抛出的异常)记录到 ViewData相应的键值里,然后我们要呈现Error这个视图。
      注意!这里已经不是Controller里了,而是另一个类,所以当然不能调用View方法返回ViewResult实例了。我们只好新建一个ViewResult实例,并将其视图名设为Error,将上下文中的DataView传过去。
      最后那行filterContext.ExcepitonHandled = true;很重要,这行的意思是告诉系统,异常已经处理,不要再次处理了。
应用拦截器
      好了,拦截器建立完了,要怎么应用到相应的Action上呢?如果你使用过Spring,你一定对其AOP是实现之麻烦深有感触,如果你和我一样讨厌写各 种XML的话,你真是太幸福了。因为在ASP.NET MVC中,应用拦截器简直是轻松加愉快。只要将拦截器当做Attribute写在要应用此拦截器的Action上就行了。看代码。
AnnounceController.cs:

 1using System;
 2using System.Collections.Generic;
 3using System.Linq;
 4using System.Web;
 5using System.Web.Mvc;
 6using System.Web.Mvc.Ajax;
 7using MVCDemo.Models;
 8using MVCDemo.Models.Interfaces;
 9using MVCDemo.Models.Entities;
10using MVCDemo.Controllers.Filters;
11
12namespace MVCDemo.Controllers
13{
14    public class AnnounceController : Controller
15    {
16        public ActionResult Release()
17        {
18            ICategoryService cServ = ServiceBuilder.BuildCategoryService();
19            List<CategoryInfo> categories = cServ.GetAll();
20            ViewData["Categories"= new SelectList(categories, "ID""Name");
21            return View("Release");
22        }

23
24        [LoggerFilter()]
25        [ExceptionFilter()]
26        public ActionResult DoRelease()
27        {
28            AnnounceInfo announce = new AnnounceInfo()
29            {
30                ID = 1,
31                Title = Request.Form["Title"],
32                Category = Int32.Parse(Request.Form["Category"]),
33                Content = Request.Form["Content"],
34            }
;
35
36            IAnnounceService aServ = ServiceBuilder.BuildAnnounceService();
37            aServ.Release(announce);
38
39            ViewData["Announce"= announce;
40
41            System.Threading.Thread.Sleep(2000);
42            ViewData["Time"= DateTime.Now;
43            System.Threading.Thread.Sleep(2000);
44
45            return View("ReleaseSucceed");
46        }

47    }

48}


      看到没有,只要在DoRelease上写这么两个Attribute,一切就完成了,至于什么时候该调用什么拦截器,都是框架帮你完成了。注意一点,为了 让我们看出拦截器的时序,我们在DoRelease中加了一点东西,就是加了一个ViewData["Time"],里面记录了执行此Action的时 间,因为日志拦截器在前后都会记录时间,我们通过比较时间就可以看出执行顺序了。至于那两个Sleep则是让效果更明显的,这行代码的意思是让程序在这里 延迟2秒。
      要执行这个程序,我们还要改一下ReleaseSucceed.aspx视图,其实就是加几个地方显示ViewData里相应的数据。
ReleaseSucceed.aspx:

 1<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ReleaseSucceed.aspx.cs" Inherits="MVCDemo.Views.Announce.ReleaseSucceed" %>
 2<%@ Import Namespace="MVCDemo.Models.Entities" %>
 3
 4<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 5
 6<html xmlns="http://www.w3.org/1999/xhtml" >
 7<head runat="server">
 8    <title></title>
 9</head>
10<body>
11    <% AnnounceInfo announce = ViewData["Announce"as AnnounceInfo; %>
12    <div>
13        <h1>MVC公告发布系统——发布公告成功</h1>
14        <dl>
15            <dt>ID:</dt>
16            <dd><%= announce.ID %></dd>
17            <dt>标题:</dt>
18            <dd><%= announce.Title %></dd>
19            <dt>类别ID:</dt>
20            <dd><%= announce.Category %></dd>
21            <dt>内容:</dt>
22            <dd><%= announce.Content %></dd>
23            <dt>发布时间:</dt>
24            <dd><%= ViewData["Time"%></dd>
25        </dl>
26        <p><%= ViewData["ExecutingLogger"%></p>
27        <p><%= ViewData["ExecutedLogger"%></p>
28    </div>
29</body>
30</html>


      现在可以提交一则公告看结果了:

 
      没有问题,拦截器方法顺利执行,而且从时间可以看出,OnActionExecuting先执行,Action执行,然后OnActionExecuted执行。
      下面我们来看看异常拦截器的效果。要触发异常拦截器,首先要抛出一个异常,所以,我们在业务逻辑组件做点手脚。将MockAnnounceServices的Release方法改成如下:

1/// <summary>
2/// 发布公告
3/// </summary>
4/// <param name="announce"></param>

5public void Release(AnnounceInfo announce)
6{
7    throw new Exception("发布公告失败了!原因?没有原因!我是业务组件,我说失败就失败!");
8    return;
9}

      另外,我们还要实现一个Error.aspx视图,这是在异常拦截器中定义的错误视图。我们将它新建在Views/Shared下就可以了。顺便说一下, 共用的视图一般放在Shared下,因为ASP.NET MVC的视图寻找机理是当与Controller同名目录下不存在时,就到Shared下看看有没有此视图。
Error.aspx:

 1<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Error.aspx.cs" Inherits="MVCDemo.Views.Shared.Error" %>
 2
 3<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 4
 5<html xmlns="http://www.w3.org/1999/xhtml" >
 6<head runat="server">
 7    <title></title>
 8</head>
 9<body>
10    <div>
11        <h1>系统发生异常</h1>
12        <%= ViewData["ErrorMessage"%>
13    </div>
14</body>
15</html>

      好了,现在我们再提交新公告,会返回如下结果:

 
      很明显,业务组件抛出了异常,但是我们的Action方法中并没有用try…catch处理,但是异常拦截器成功拦截了异常,并做了相应处理。
      我们再回过头看看,使用了拦截器后,代码是不是很清晰呢。
小结
      通过本文,朋友们应该可以掌握拦截器的基本使用以及使用它在表示层实现AOP了。下一篇作为本系列的终结篇,将对ASP.NET MVC做一个全面的讨论,并与Web Form模型进行一个比较,使朋友们看清其优势、劣势,从而更好的学习使用这个框架。

[SQLServer]SQL Server数据导入导出资料大全

mikel阅读(468)

大家打开这个链接可以看到很多数据库的连接方法。http://www.connectionstrings.com
这些数据库之间的数据交换就是这个贴子所要总结的内容。

(一)SQL Server之间
把远程数据库中的数据导入到本地数据库。
http://community.csdn.net/Expert/topic/5079/5079649.xml?temp=.7512018
http://community.csdn.net/Expert/topic/5011/5011278.xml?temp=.1658899
http://community.csdn.net/Expert/topic/4982/4982625.xml?temp=.8189966

把A库里的其中几个表和视图导入B库
http://community.csdn.net/Expert/topic/5042/5042648.xml?temp=.2556574

SQL2005的数据库导入SQL2000中
http://community.csdn.net/Expert/topic/4954/4954820.xml?temp=.3408625
在SQL2005中 如何导入 SQL2000中的Analysis Service ?
http://community.csdn.net/Expert/topic/4713/4713032.xml?temp=2.752322E-02

英文版sql server2005中bcp导出中文乱码问题
http://community.csdn.net/Expert/topic/5024/5024662.xml?temp=.7404596

如何将一个由SQL保存出来的*.bas文件再导回到SQL中
http://community.csdn.net/Expert/topic/4944/4944630.xml?temp=.8225672

(二)SQL Server –> Access

将SQL数据导出至Access(SQL与Access同一台机器上)
http://community.csdn.net/Expert/topic/4919/4919937.xml?temp=.2461359
将SQL数据导出至Access(SQL与Access不在同一台机器上)
http://community.csdn.net/Expert/topic/4906/4906691.xml?temp=.1377222
http://community.csdn.net/Expert/topic/4917/4917015.xml?temp=.7591364

(三)Access –> SQL Server
http://faq.csdn.net/FAQUnfurl.aspx?id=214875

为什么access与SQLServer2000导入导出时,数据库结构变了,默认主键,自动编号全没了?
http://community.csdn.net/Expert/topic/4712/4712570.xml?temp=.3942224

(四)txt(记事本)–> SQL Server
http://community.csdn.net/Expert/topic/5045/5045602.xml?temp=.0278284
TXT文件导入数据库出现乱码
http://community.csdn.net/Expert/topic/4939/4939026.xml?temp=.4465296
关于上千份大文本存入SQLServer
http://community.csdn.net/Expert/topic/4973/4973969.xml?temp=.4392816

(五)SQL Server –> txt
http://community.csdn.net/Expert/topic/4906/4906039.xml?temp=.6642267
SQL导出TXT或HTML求助
http://community.csdn.net/Expert/topic/5031/5031048.xml?temp=1.302737E-02

(六)Excel –> SQL Server
http://community.csdn.net/Expert/topic/5002/5002120.xml?temp=.4375727
http://community.csdn.net/Expert/topic/5086/5086098.xml?temp=.6402094
http://community.csdn.net/Expert/topic/4940/4940738.xml?temp=.8665125
http://community.csdn.net/Expert/topic/4938/4938969.xml?temp=1.918972E-03
http://community.csdn.net/Expert/topic/4892/4892120.xml?temp=.1775324
使用Excel导入数据库时,遇到这么个奇怪的问题,当Excel的一列中的数据类型明显不同时就会直接eof,??
http://community.csdn.net/Expert/topic/4929/4929620.xml?temp=.2570154

(七)DBF –> SQL Server
http://community.csdn.net/Expert/topic/5070/5070623.xml?temp=6.957644E-02

其他问题

怎样把数据库中的题目经过vb 导到word
http://faq.csdn.net/FAQUnfurl.aspx?id=215243

使用作业来完成DTS操作。
http://community.csdn.net/Expert/topic/5046/5046974.xml?tep=.9785425

还可以看看这个链接
http://blog.csdn.net/dutguoyi/archive/2006/10/16/1337274.aspx

xml –> sql server
http://community.csdn.net/Expert/topic/5041/5041228.xml?temp=.8233911

 oracle –> sql server
http://community.csdn.net/Expert/topic/5019/5019542.xml?temp=2.604312E-02

http://support.microsoft.com/kb/320125

http://fufun.cn/show.aspx?id=dC8yMDAyMDUzMC8xNS83NjUxOTEuaHRtbA_x003D__x003D_

在用Bulk Insert导入数据时的日期时间格式问题,
原因:bulk insert 不能转换数据类型,如果时间格式不正确就会出错。
http://community.csdn.net/Expert/topic/5100/5100692.xml?temp=.0559656

Excel –> SQL Server
导入时添加额外列,
例如 EXECL表的结构为 名称,内容,类别,
     SQLserver表的结构为 名称,内容,类别,属性
http://community.csdn.net/Expert/topic/5105/5105613.xml?temp=.3277399

补上
Excel –> SQL Server
导入时列名调整补充
http://community.csdn.net/Expert/topic/5086/5086098.xml?temp=.5973932

SQL Server 2005 –> SQL Server 2000
http://dev.csdn.net/author/taito/840c28a03ec0432492db18a329125bb5.html
http://community.csdn.net/Expert/topic/4954/4954820.xml?temp=.495083

SQL Server 2005 –> SQL Server 2000
用sql2005的导入导出工具将所有SQL2005的表和数据导出到SQL2000下,但是所有的主键、索引、关系、默认值全部丢了。
http://community.csdn.net/Expert/topic/4905/4905590.xml?temp=6.176394E-02

MySql –> SQL Server
http://topic.csdn.net/t/20031203/09/2521118.html
http://topic.csdn.net/t/20030407/11/1627991.html

SQL Server –> DB2
http://www.21cnvip.com/csdn/default.aspx?q=20021105/10/1149089.html

大家可以在下面的链接来搜索CSDN技术社区文档,很大的技术宝藏啊。
http://search.csdn.net/search/null/1/dev/

SQL Server 2000 –> SQL Server 7.0
SQL2000数据导入到SQL7,那些设置为主键的没有了
http://community.csdn.net/Expert/topic/5004/5004254.xml?temp=.1570246

SQL Server 2005 –> SQL Server 2000
2005导出的脚本为什么在2000运行总是出错?
http://community.csdn.net/Expert/topic/4682/4682496.xml?temp=.6038324

SQL Server之间复制数据库
http://community.csdn.net/Expert/topic/4835/4835266.xml?temp=.7495233

SQL Server 2000 –> SQL Server 2000
DTS包的制作
http://community.csdn.net/Expert/topic/5006/5006594.xml?temp=.2426111

SQL Server 2005 –> Excel
数据长度为255,出错
http://community.csdn.net/Expert/topic/4951/4951804.xml?temp=.2144739

SQL Server 2005 –> SQL Server 2000
http://community.csdn.net/Expert/topic/5089/5089204.xml?temp=.4461328

SQL Server 2000 –> SQL Server 2000
导出表的所有结构、所有数据
http://community.csdn.net/Expert/topic/5092/5092752.xml?temp=.8595545

From: http://blog.csai.cn/user1/19065/archives/2006/8916.html

[XML]在C#.net中如何操作XML

mikel阅读(634)

C#.net中如何操作XML
需要添加的命名空间:
using System.Xml;

定义几个公共对象:
XmlDocument xmldoc ;
XmlNode xmlnode ;
XmlElement xmlelem ;

1,创建到服务器同名目录下的xml文件:

方法一:
xmldoc = new XmlDocument ( ) ;
//加入XML的声明段落,<?xml version="1.0" encoding="gb2312"?>
XmlDeclaration xmldecl;
 xmldecl = xmldoc.CreateXmlDeclaration("1.0","gb2312",null);
 xmldoc.AppendChild ( xmldecl);
//加入一个根元素
xmlelem = xmldoc.CreateElement ( "" , "Employees" , "" ) ;
xmldoc.AppendChild ( xmlelem ) ;
//加入另外一个元素
for(int i=1;i<3;i++)
{

XmlNode root=xmldoc.SelectSingleNode("Employees");//查找<Employees>
XmlElement xe1=xmldoc.CreateElement("Node");//创建一个<Node>节点
xe1.SetAttribute("genre","李赞红");//设置该节点genre属性
xe1.SetAttribute("ISBN","2-3631-4");//设置该节点ISBN属性

XmlElement xesub1=xmldoc.CreateElement("title");
xesub1.InnerText="CS从入门到精通";//设置文本节点
xe1.AppendChild(xesub1);//添加到<Node>节点中
XmlElement xesub2=xmldoc.CreateElement("author");
xesub2.InnerText="候捷";
xe1.AppendChild(xesub2);
XmlElement xesub3=xmldoc.CreateElement("price");
xesub3.InnerText="58.3";
xe1.AppendChild(xesub3);

root.AppendChild(xe1);//添加到<Employees>节点中
}
//保存创建好的XML文档
xmldoc.Save ( Server.MapPath("data.xml") ) ;

//////////////////////////////////////////////////////////////////////////////////////
结果:在同名目录下生成了名为data.xml的文件,内容如下,
<?xml version="1.0" encoding="gb2312"?>
<Employees>
  <Node genre="李赞红" ISBN="2-3631-4">
    <title>CS从入门到精通</title>
    <author>候捷</author>
    <price>58.3</price>
  </Node>
  <Node genre="李赞红" ISBN="2-3631-4">
    <title>CS从入门到精通</title>
    <author>候捷</author>
    <price>58.3</price>
  </Node>
</Employees>

方法二:
XmlTextWriter xmlWriter;
   string strFilename = Server.MapPath("data1.xml") ;

   xmlWriter = new XmlTextWriter(strFilename,Encoding.Default);//创建一个xml文档
   xmlWriter.Formatting = Formatting.Indented;
   xmlWriter.WriteStartDocument();
   xmlWriter.WriteStartElement("Employees");

   xmlWriter.WriteStartElement("Node");
   xmlWriter.WriteAttributeString("genre","李赞红");
   xmlWriter.WriteAttributeString("ISBN","2-3631-4");

   xmlWriter.WriteStartElement("title");
   xmlWriter.WriteString("CS从入门到精通");
   xmlWriter.WriteEndElement();

   xmlWriter.WriteStartElement("author");
   xmlWriter.WriteString("候捷");
   xmlWriter.WriteEndElement();

   xmlWriter.WriteStartElement("price");
   xmlWriter.WriteString("58.3");
   xmlWriter.WriteEndElement();

   xmlWriter.WriteEndElement();

   xmlWriter.Close();
//////////////////////////////////////////////////////////////////////////////////////
结果:
<?xml version="1.0" encoding="gb2312"?>
<Employees>
  <Node genre="李赞红" ISBN="2-3631-4">
    <title>CS从入门到精通</title>
    <author>候捷</author>
    <price>58.3</price>
  </Node>
</Employees>
2,添加一个结点:

XmlDocument xmlDoc=new XmlDocument();
xmlDoc.Load(Server.MapPath("data.xml"));
XmlNode root=xmlDoc.SelectSingleNode("Employees");//查找<Employees>
XmlElement xe1=xmlDoc.CreateElement("Node");//创建一个<Node>节点
xe1.SetAttribute("genre","张三");//设置该节点genre属性
xe1.SetAttribute("ISBN","1-1111-1");//设置该节点ISBN属性

XmlElement xesub1=xmlDoc.CreateElement("title");
xesub1.InnerText="C#入门帮助";//设置文本节点
xe1.AppendChild(xesub1);//添加到<Node>节点中
XmlElement xesub2=xmlDoc.CreateElement("author");
xesub2.InnerText="高手";
xe1.AppendChild(xesub2);
XmlElement xesub3=xmlDoc.CreateElement("price");
xesub3.InnerText="158.3";
xe1.AppendChild(xesub3);

root.AppendChild(xe1);//添加到<Employees>节点中
xmlDoc.Save ( Server.MapPath("data.xml") );

//////////////////////////////////////////////////////////////////////////////////////
结果:在xml原有的内容里添加了一个结点,内容如下,
<?xml version="1.0" encoding="gb2312"?>
<Employees>
  <Node genre="李赞红" ISBN="2-3631-4">
    <title>CS从入门到精通</title>
    <author>候捷</author>
    <price>58.3</price>
  </Node>
  <Node genre="李赞红" ISBN="2-3631-4">
    <title>CS从入门到精通</title>
    <author>候捷</author>
    <price>58.3</price>
  </Node>
  <Node genre="张三" ISBN="1-1111-1">
    <title>C#入门帮助</title>
    <author>高手</author>
    <price>158.3</price>
  </Node>
</Employees>

3,修改结点的值(属性和子结点):

XmlDocument xmlDoc=new XmlDocument();
xmlDoc.Load( Server.MapPath("data.xml") );

XmlNodeList nodeList=xmlDoc.SelectSingleNode("Employees").ChildNodes;//获取Employees节点的所有子节点

foreach(XmlNode xn in nodeList)//遍历所有子节点
{
XmlElement xe=(XmlElement)xn;//将子节点类型转换为XmlElement类型
if(xe.GetAttribute("genre")=="张三")//如果genre属性值为“张三”
{
xe.SetAttribute("genre","update张三");//则修改该属性为“update张三”

XmlNodeList nls=xe.ChildNodes;//继续获取xe子节点的所有子节点
foreach(XmlNode xn1 in nls)//遍历
{
XmlElement xe2=(XmlElement)xn1;//转换类型
if(xe2.Name=="author")//如果找到
{
xe2.InnerText="亚胜";//则修改
}
}
}
}
xmlDoc.Save( Server.MapPath("data.xml") );//保存。

//////////////////////////////////////////////////////////////////////////////////////
结果:将原来的所有结点的信息都修改了,xml的内容如下,
<?xml version="1.0" encoding="gb2312"?>
<Employees>
  <Node genre="李赞红" ISBN="2-3631-4">
    <title>CS从入门到精通</title>
    <author>候捷</author>
    <price>58.3</price>
  </Node>
  <Node genre="李赞红" ISBN="2-3631-4">
    <title>CS从入门到精通</title>
    <author>候捷</author>
    <price>58.3</price>
  </Node>
  <Node genre="update张三" ISBN="1-1111-1">
    <title>C#入门帮助</title>
    <author>亚胜</author>
    <price>158.3</price>
  </Node>
</Employees>

4,修改结点(添加结点的属性和添加结点的自结点):
XmlDocument xmlDoc=new XmlDocument();
xmlDoc.Load( Server.MapPath("data.xml") );

XmlNodeList nodeList=xmlDoc.SelectSingleNode("Employees").ChildNodes;//获取Employees节点的所有子节点

foreach(XmlNode xn in nodeList)
{
XmlElement xe=(XmlElement)xn;
xe.SetAttribute("test","111111");

XmlElement xesub=xmlDoc.CreateElement("flag");
xesub.InnerText="1";
xe.AppendChild(xesub);
}
xmlDoc.Save( Server.MapPath("data.xml") );

//////////////////////////////////////////////////////////////////////////////////////
结果:每个结点的属性都添加了一个,子结点也添加了一个,内容如下,
<?xml version="1.0" encoding="gb2312"?>
<Employees>
  <Node genre="李赞红" ISBN="2-3631-4" test="111111">
    <title>CS从入门到精通</title>
    <author>候捷</author>
    <price>58.3</price>
    <flag>1</flag>
  </Node>
  <Node genre="李赞红" ISBN="2-3631-4" test="111111">
    <title>CS从入门到精通</title>
    <author>候捷</author>
    <price>58.3</price>
    <flag>1</flag>
  </Node>
  <Node genre="update张三" ISBN="1-1111-1" test="111111">
    <title>C#入门帮助</title>
    <author>亚胜</author>
    <price>158.3</price>
    <flag>1</flag>
  </Node>
</Employees>

5,删除结点中的某一个属性:
XmlDocument xmlDoc=new XmlDocument();
xmlDoc.Load( Server.MapPath("data.xml") );
XmlNodeList xnl=xmlDoc.SelectSingleNode("Employees").ChildNodes;
foreach(XmlNode xn in xnl)
{
XmlElement xe=(XmlElement)xn;
xe.RemoveAttribute("genre");//删除genre属性

XmlNodeList nls=xe.ChildNodes;//继续获取xe子节点的所有子节点
foreach(XmlNode xn1 in nls)//遍历
{
XmlElement xe2=(XmlElement)xn1;//转换类型
if(xe2.Name=="flag")//如果找到
{
xe.RemoveChild(xe2);//则删除
}
}
}
xmlDoc.Save( Server.MapPath("data.xml") );

//////////////////////////////////////////////////////////////////////////////////////]
结果:删除了结点的一个属性和结点的一个子结点,内容如下,
<?xml version="1.0" encoding="gb2312"?>
<Employees>
  <Node ISBN="2-3631-4" test="111111">
    <title>CS从入门到精通</title>
    <author>候捷</author>
    <price>58.3</price>
  </Node>
  <Node ISBN="2-3631-4" test="111111">
    <title>CS从入门到精通</title>
    <author>候捷</author>
    <price>58.3</price>
  </Node>
  <Node ISBN="1-1111-1" test="111111">
    <title>C#入门帮助</title>
    <author>亚胜</author>
    <price>158.3</price>
  </Node>
</Employees>

6,删除结点:
XmlDocument xmlDoc=new XmlDocument();
xmlDoc.Load( Server.MapPath("data.xml") );
XmlNode root=xmlDoc.SelectSingleNode("Employees");
XmlNodeList xnl=xmlDoc.SelectSingleNode("Employees").ChildNodes;
for(int i=0;i<xnl.Count;i++)
{
XmlElement xe=(XmlElement)xnl.Item(i);
if(xe.GetAttribute("genre")=="张三")
{
root.RemoveChild(xe);
if(i<xnl.Count)i=i-1;
}
}
xmlDoc.Save( Server.MapPath("data.xml") );

//////////////////////////////////////////////////////////////////////////////////////]
结果:删除了符合条件的所有结点,原来的内容:

<?xml version="1.0" encoding="gb2312"?>
<Employees>
  <Node genre="李赞红" ISBN="2-3631-4">
    <title>CS从入门到精通</title>
    <author>候捷</author>
    <price>58.3</price>
  </Node>
  <Node genre="李赞红" ISBN="2-3631-4">
    <title>CS从入门到精通</title>
    <author>候捷</author>
    <price>58.3</price>
  </Node>
  <Node genre="张三" ISBN="1-1111-1">
    <title>C#入门帮助</title>
    <author>高手</author>
    <price>158.3</price>
  </Node>
  <Node genre="张三" ISBN="1-1111-1">
    <title>C#入门帮助</title>
    <author>高手</author>
    <price>158.3</price>
  </Node>
</Employees>

删除后的内容:
<?xml version="1.0" encoding="gb2312"?>
<Employees>
  <Node genre="李赞红" ISBN="2-3631-4">
    <title>CS从入门到精通</title>
    <author>候捷</author>
    <price>58.3</price>
  </Node>
  <Node genre="李赞红" ISBN="2-3631-4">
    <title>CS从入门到精通</title>
    <author>候捷</author>
    <price>58.3</price>
  </Node>
</Employees>

 7,按照文本文件读取xml

System.IO.StreamReader myFile =new 
System.IO.StreamReader(Server.MapPath("data.xml"),System.Text.Encoding.Default);
//注意System.Text.Encoding.Default
string myString = myFile.ReadToEnd();//myString是读出的字符串
myFile.Close();

[Lucene]信息检索的函数库Lucene的使用总结

mikel阅读(701)

简单介绍:
Lucene是一个信息检索的函数库(Library),利用它你可以为你的应用加上索引和搜索的功能.

Lucene的使用者不需要深入了解有关全文检索的知识,仅仅学会使用库中的一个类,你就为你的应用实现全文检索的功能.

不过千万别以为Lucene是一个google那样的搜索引擎,Lucene甚至不是一个应用程序,它仅仅是一个工具,一个Library.你也可以把它理解为一个将索引,搜索功能封装的很好的一套简单易用的API.利用这套API你可以做很多有关搜索的事情,而且很方便。
发展历史:参见《.NET 的 Lucene 》
详细使用帮助:http://www.lucene.com.cn/net.htm (包含了建立索引/对索引进行搜索/删除索引中的文档/更新索引中的文档/查询语句/多个条件查询)
90%的语法在上述使用帮助都可以找到答案。
上面的使用帮助对排序说明的比较少,补充如下:
可以通过 SortField 的构造参数,我们可以设置排序字段,排序条件,以及倒排。
Sort sort = new Sort(new SortField(FieldName, SortField.DOC, false));
IndexSearcher searcher = new IndexSearcher(reader);
Hits hits = searcher.Search(query, sort);
排序对搜索速度影响还是很大的,尽可能不要使用多个排序条件。
Lucene.Net的语言处理包中Lucene.Net.Analysis.Cn的Bug :http://www.cnblogs.com/dudu/archive…6/22/17783.aspx
如何联合两个索引查询 / 分布搜索:
我们可以使用 MultiReader 或 MultiSearcher 搜索多个索引库。
MultiReader reader = new MultiReader(new IndexReader[] { IndexReader.Open(@"c:\index"), IndexReader.Open(@"\\server\index") });
IndexSearcher searcher = new IndexSearcher(reader);
Hits hits = searcher.Search(query);

IndexSearcher searcher1 = new IndexSearcher(reader1);
IndexSearcher searcher2 = new IndexSearcher(reader2);
MultiSearcher searcher = new MultiSearcher(new Searchable[] { searcher1, searcher2 });
Hits hits = searcher.Search(query);
还可以使用 ParallelMultiSearcher 进行多线程并行搜索。
如何合并索引库?
将 directory1 合并到 directory2 中。
Directory directory1 = FSDirectory.GetDirectory("index1", false);
Directory directory2 = FSDirectory.GetDirectory("index2", false);
IndexWriter writer = new IndexWriter(directory2, analyzer, false);
writer.AddIndexes(new Directory[] { directory });
Console.WriteLine(writer.DocCount());
writer.Close();
关于IndexWriter和IndexReader
Add Optimize Merge操作都是由IndexWriter来做的
Delete则是通过IndexReader完成
文档有一句话“即同一时间只允许IndexWriterIndexReader打开同一份索引.不能允许两个同时打开一份索引

记住IndexReader并不是查询索引的时候要用的,从字面含有好像是读取,所以可以同时查询索引和写入索引。

我的使用Lucene.net成功案例:http://video.5913.com/

[Flex]利用HTTPService实现Flex与服务器端低数据量通信

mikel阅读(596)

        Flex作为企业级的开发平台,与服务器端的通信是至关重要的。传统的Flash与服务器端主要通过HTTP、WebService和Flash Remoting方式通信,Flex除了保留了Flash平台与服务端通信方式外增加了一系列的高级服务功能。Flex与服务端通信主要分为两大类:一类 是通过传统的HTTP方式发送请求来和服务器端进行交互,另外一类则是通过LCDS等与服务端进行通信。

      低数据量的通信我们一般会选择Http方式来进行通信。通过HTTP方式Flex可以与任意服务器端进行通信。通过HTTP与服务器端通信又可以通过 HTTP请求方式和WebService实现。前者使用异步的HTTP请求方式,使用方式与Ajax一致,而后者则是通过标准的WebService协议 与服务端进行通信。下面我们看下HTTPService方式的通信,查阅相关的帮助文档我们可以知道HTTPService一些常用的方法和属性:

属性

method:发送HTTP请求的方法

 url : 请求服务的位置

request:发送请求的参数

requestTimeout:请求超时的时间

useProxy:是否使用代理的别名服务

方法:

send:参数为object类型默认为null,返回值类型为AsyncToken,执行一个HTTPService的请求

下面我们通过一个获取新浪体育新闻汇总的示例来说明HTTPService的使用

 


<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="sinaSport.send()">
<mx:Style>
    global
    {
        fontSize:14pt;
    }
</mx:Style>
    
<mx:HTTPService id="sinaSport" url="http://rss.sina.com.cn/roll/sports/hot_roll.xml" useProxy="false">
    
</mx:HTTPService>
    
<mx:Panel x="53" y="90" width="975" height="461" layout="absolute" title="新浪体育要闻汇总 ">
    
<mx:DataGrid id="sportContent" x="23.5" y="10" width="911.5" dataProvider="{sinaSport.lastResult.rss.channel.item}" height="175">
        
<mx:columns>
            
<mx:DataGridColumn  width="300" headerText="标题" dataField="title"/>
            
<mx:DataGridColumn  width="150" headerText="作者" dataField="author" />
            
<mx:DataGridColumn  width="150" headerText="日期" dataField="pubDate" />
        
</mx:columns>
    
</mx:DataGrid>
    
<mx:TextArea x="23" y="193" width="912" height="183" htmlText="{sportContent.selectedItem.description}"/>
 
<mx:LinkButton x="855" y="384" label="详细信息" click="navigateToURL(new URLRequest(sportContent.selectedItem.link))"/>
    
</mx:Panel>
    
</mx:Application>

示例运行效果如下图:

在上面的代码中通过 如下代码声明了HTTPService 数据的位置


<mx:HTTPService id="sinaSport" url="http://rss.sina.com.cn/roll/sports/hot_roll.xml" useProxy="false">
    
</mx:HTTPService>

 

通过


<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="sinaSport.send()">

进行数据的发送

服务器端返回的结果则是通过sinaSport.lastResult来引用最后通过DataGrid来显示数据。

         从这个简单的例子我们可以看出因为HTTPService不是标准协议,基于HTTPService的通信方式访问的数据格式是由服务端来制定的,所以在 使用中要求Flex端与服务端的数据处理方式和交换格式一致。基于HTTP协议访问一般都通过纯文本数据进行传输。Flex能够轻松的将之转换为 ActionScript对象。

[JQuery]JQuery1.3发布了

mikel阅读(624)

2009-1-14,JQuery 1.3发布正式版,尽管之前版本的jQ已经让我们感受到了诸多便利,但是1.3还是给了我们额外的惊喜。
大家可以参考JQuery对于这个版本发布的官方文档:http://docs.jQuery.com/Release:jQuery_1.3
在官方的文档里你可以看到更详细的数据,不过在本篇里你可以看到更细节的分析。
==Sizzle,独立的css选择器引擎==
jQuery在之前的版本里已经逐渐酝酿出css选择器模块的独立。因为Sizzle的独立性,jQuery和Dojo开发组也有意通过Sizzle来开展长期合作(也就是共享部分代码)。
Sizzle也兼容之前版本的jQuery,那些依赖于低版本的jQuery的代码并无重写之忧。
Sizzle在最常见的使用场景中,也有了不同程度的性能提高。(什么是最常见使用的场景呢?可以参考http://ejohn.org/blog/selectors-that-people-actually-use/)
==Live,持久化事件绑定==
通常我们在使用jQuery的过程中,新构造的DOMElement也需要重新完成其事件绑定的逻辑。而jQuery 1.3 里的live函数可以让我们用类似于css behavior的方式来为未来要产生的DOMElement绑定事件。(当然你要拿它当css用,也无妨)
随之对应的,解除这种持久化事件绑定的方式可以用die来完成。
在sizzle.js的源码开头的几行,我们可以看到实现的思路。
document.addEventListener("DOMAttrModified", invalidate, false);
document.addEventListener("DOMNodeInserted", invalidate, false);
document.addEventListener("DOMNodeRemoved", invalidate, false);
==Event对象重封装==
jQuery.Event的主要功能被封装。(jQ有分拆IPO的倾向)
==html注入重写==
性能大幅提高(about 6x faster overall)。
还提供了新用法$("<script/>") 以代替$(document.createElement("script"))
==Offset重写==
性能大幅提高(almost 3x jump)
==jQuery.support,浏览器识别==
jQuery.browser是用useragent来识别浏览器,新增的jQuery.support以js的功能来识别浏览器。
==更新==
jQuery UI and the Validation plugin会同步更新。
如果你有依赖低版本的jQuery的代码的话,请阅读potentially-breaking changes
==Downloading==
jQuery Minified (18kb Gzipped)
jQuery Regular (114kb)
也可以用 http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js for a quickly-loading jQuery
==不兼容的Changes==
[@attr]不再需要写@了。(个人感觉这是一个很坏的change)
使用trigger( event, [data] )触发的事件现在会造成冒泡。(言下之意就是以前不会,以前没在意这个细节)
ready()不会等待所有的.css文件下载完毕才执行。(页面上的css引用要写在js前面了)
isFunction被简化。
(原来 !!fn && typeof fn != "string" && !fn.nodeName && fn.constructor != Array && /^[\s[]?function/.test( fn + "" )
现在 toString.call(obj) === "[object Function]" ,有很多你想不到的东西的typeof会是"Function")
逗号选择器的顺序有可能改变(因为Browsers that support querySelectorAll (Safari, Firefox 3.1+, Opera 10+, IE 8+),而它们返回的顺序和jQuery现有逻辑不同)
trigger 和 triggerHandler 原来提供的data形参可以接受一个数组,现在必须是类似于options的对象
(原来按以下对象属性的数组也可以被接受,{type: type,target: elem,preventDefault: function(){},stopPropagation: function(){},timeStamp: now()})
"extra"函数被去除(原来就没有写进文档里),如果trigger 和 triggerHandler 里data参数里提供了多余的成员,如{fa:function(){},fb:function(){},fc:function(){},type: type,target: elem,preventDefault: function(){},stopPropagation: function(){},timeStamp: now()},如果该成员isFunction的话,也会随trigger 和 triggerHandler被执行。
interal jQuery.event.trigger不再返回最后一个hander的返回值,只返回true or false(需要的话可以用jQuery.Event 来作为返回值的句柄)
需要在标准模式下运行jQuery,因为有一些函数在quirks mode运行不正确(Safari下甚至如此重要的一些选择器函数都会出错)
==增强特性==
(FEATURES)
===Core===
New queueing methods which you can use to manage existing queues (such as the animation queue) or construct new ones to manage completely separate workflows.(不是很理解有什么个特法)
jQuery 实例对象新增了两个属性selector and .context 。(以唤回你在构造这些对象时的记忆,jQuery( expression, context ) )
===Selector===
新增支持 复杂的not表达式。如 $(":not(a, b)") and $(":not(div a)")
not表达式其实是反向选择器,老实说我觉得这是一个很重要的特性
===Attributes===
jQuery实例对象新增成员函数toggleClass( String class, Boolean switch )
===Traversing===
jQuery实例对象新增成员函数 .closest( selector ) 以定位位置最接近的符合selector的ancestor element(祖先元素)。(会递归匹配parentNode,我原以为parent( [expr] ) 是做这个用的,后来发现parent( [expr] )只是很直白的选出以expr构造出的jQuery实例对象或者jQuery实例对象this的parentNode)
jQuery实例对象成员函数is()可以支持复杂选择器
===Manipulation===
$("<script/>")相当于原来的$(document.createElement("script")),前面介绍过了
===CSS===
Offset 重写了,性能提高,前面介绍过了
===Events===
Live Events
jQuery Event Object
.trigger()冒泡
(前面都介绍过了)
===Effects===
.hide() and .show() 重写,性能提高。
animate更加平滑,因为原来只控制width, height,opacity,现在连margin and padding控制了
未提供duration参数的animate调用不会有渐变,而是直接被同步化(因为原来animate的渐变都是异步的)的设为最终值
.toggle( Boolean switch ) 所有类似于toggle的函数(如toggleClass)都增加了switch这个参数支持,把toggle类的对象分为正反两种状态的话(如采用和不 采用,显示和隐藏),if(switch)则为正状态,反之亦然。
参考下面的代码:
var flip = 0;
$("button").click(function () {
$("p").toggle( flip++ % 2 == 0 );
});
原来无switch参数的时候相当于总是( flip++ % 2 == 0 ),现在我们可以自己控制了。
这是一个很好的新增特性。
jQuery.fx.off=true用来禁止所有animate
===Ajax===
jQuery.ajax( options )
options新增了{Function(data, type) dataFilter},可以用来在jQuery.ajax返回data前再处理一下data(比如过滤)
options新增了{Function() xhr},以xhr返回值作为XMLHttpRequest对象。这是一个很有用的增强,在跨域ajax时,一种做法是制造一个假的XMLHttpRequest。
load( url, [data], [callback] )的参数data可以是String了
===Utilities===
新增了jQuery.isArray( obj )函数
===Internals===
不再使用ua来作为识别浏览器的判断
YUI Compressor作为默认jQuery压缩工具
jQuery不再使用.constructor and instanceof(Will help to give jQuery better cross-frame support.)
==TESTING==
brabra
==PERFORMANCE==
css选择器,delegate过滤器,DOM修改操作(尤其是插入),.offset(),.hide()/.show() 都获得了不同程度的性能改进

[Lucene]Annotated Lucene:第三节 索引文件结构(1)

mikel阅读(670)

Annotated Lucene(源码剖析中文版)

Annotated Lucene 作者:naven  


  

3.1      索引文件结构

  Lucene使用文件扩展名标识不同的索引文件,文件名标识不同版本或者代(generation)的索引片段(segment)。如.fnm文件存储域Fields名称及其属性,.fdt存储文档各项域数据,.fdx存储文档在fdt中的偏移位置即其索引文件,.frq存储文档中term位置数据,.tii文件存储term字典,.tis文件存储term频率数据,.prx存储term接近度数据,.nrm存储调节因子数据,另外segments_X文件存储当前最新索引片段的信息,其中X为其最新修改版本,segments.gen存储当前版本即X值,这些文件的详细介绍上节已说过了。

    下面的图描述了一个典型的lucene索引文件列表:

     

lucene-indexfiles.jpg

    

如果将它们的关系划成图则如下所示(该图来自网上,出处忘了):

 

image010.jpg

 

这些文件中存储数据的详细结构是怎样的呢,下面几个小节逐一介绍它们,熟悉它们的结构非常有助于优化Lucene的查询和索引效率和存储空间等。

    

         

3.2  每个Index包含的单个文件

下面几节介绍的文件存在于每个索引index中,并且只有一份。 

3.2.1 Segments文件

    

索引中活动(active)的Segments被存储在segment info文件中,segments_N,在索引中可能会包含一个或多个segments_N文件。然而,最大一代的那个文件(the one with largest generation)是活动的片断文件(这时更旧的segments_N文件依然存在(are present)是因为它们暂时(temporarily)还不能被删除,或者,一个writer正在处理提交请求(in the process of committing),或者一个用户定义的(customIndexDeletionPolicy正被使用)。这个文件按照名称列举每一个片断(lists each segment by name),详细描述分离的标准(seperate norm)和要删除的文件(deletion files),并且还包含了每一个片断的大小。

  

2.1版本来说,还有一个文件segments.gen。这个文件包含了该索引中当前生成的代(current generation)(segments_N中的_N)。这个文件仅用于一个后退处理(fallback)以防止(in case)当前代(current generation)不能被准确地(accurately)通过单独地目录文件列举(by directory listing alone)来确定(determened)(由于某些NFS客户端因为基于时间的目录(time-based directory)的缓存终止(cache expiration)而引起)。这个文件简单地包含了一个int32的版本头(version header)(SegmentInfos.FORMAT_LOCKLESS=-2),遵照代的记录(followed by the generation recorded)规则,对int64来说会写两次(write twice)。

    

版本 包含的项 数目 类型 描述
2.1之前版本 Format 1 Int32 Lucene1.4中为-1,而在Lucene 2.1中为-3SegmentsInfos.FORMAT_SINGLE_NORM_FILE
Version 1 Int64 统计在删除和添加文档时,索引被更改了多少次。
NameCounter 1 Int32 用于为新的片断文件生成新的名字。
SegCount 1 Int32 片断的数目
SegName SegCount String 片断的名字,用于所有构成片断索引的文件的文件名前缀。
SegSize SegCount Int32 包含在片断索引中的文档的数目。
2.1及之后版本 Format 1 Int32 Lucene 2.1Lucene 2.2中为-3SegmentsInfos.FORMAT_SINGLE_NORM_FILE
Version 1 Int64 同上
NameCounter 1 Int32 同上
SegCount 1 Int32 同上
SegName SegCount String 同上
SegSize SegCount Int32 同上
DelGen SegCount Int64 为分离的删除文件的代的数目(generation count of the separate deletes file),如果值为-1,表示没有分离的删除文件。如果值为0,表示这是一个2.1版本之前的片断,这时你必须检查文件是否存在_X.del这样的文件。任意大于0的值,表示有分离的删除文件,文件名为_X_N.del
HasSingleNormFile SegCount Int8 该值如果为1,表示Norm域(field)被写为一个单一连接的文件(single joined file)中(扩展名为.nrm),如果值为0,表示每一个fieldnorms被存储为分离的.fN文件中,参考下面的“标准化因素(Normalization Factors)”
NumField SegCount Int32 表示NormGen数组的大小,如果为-1表示没有NormGen被存储。
NormGen SegCount * NumField Int64 记录分离的标准文件(separate norm file)的代(generation),如果值为-1,表示没有normGens被存储,并且当片断文件是2.1之前版本生成的时,它们全部被假设为0assumed to be 0)。而当片断文件是2.1及更高版本生成的时,它们全部被假设为-1。这时这个代(generation)的意义与上面DelGen的意义一样。
IsCompoundFile SegCount Int8 记录是否该片断文件被写为一个复合的文件,如果值为-1表示它不是一个复合文件(compound file),如果为1则为一个复合文件。另外如果值为0,表示我们需要检查文件系统是否存在_X.cfs
2.3 Format 1 Int32 Lucene 2.3中为-4 (SegmentInfos.FORMAT_SHARED_DOC_STORE)
Version 1 Int64 同上
NameCounter 1 Int32 同上
SegCount 1 Int32 同上
SegName SegCount String 同上
SegSize SegCount Int32 同上
DelGen SegCount Int64 同上
DocStoreOffset 1 Int32 如果值为-1则该segment有自己的存储文档的fields数据和term vectors的文件,并且DocStoreSegment, DocStoreIsCompoundFile不会存储。在这种情况下,存储fields数据(*.fdt*.fdx文件)以及term vectors数据(*.tvf*.tvd*.tvx文件)的所有文件将存储在该segment下。另外,DocStoreSegment将存储那些拥有共享的文档存储文件的segmentDocStoreIsCompoundFile值为1如果segment存储为compound文件格式(如.cfx文件),并且DocStoreOffset值为那些共享文档存储文件中起始的文档编号,即该segment的文档开始的位置。在这种情况下,该segment不会存储自己的文档数据文件,而是与别的segment共享一个单一的数据文件集。
[DocStoreSegment] 1 String 如上
[DocStoreIsCompoundFile] 1 Int8 如上
HasSingleNormFile SegCount Int8 同上
NumField SegCount Int32 同上
NormGen SegCount * NumField Int64 同上
IsCompoundFile SegCount Int8 同上
2.4及以上 Format 1 Int32 Lucene 2.4中为-7 (SegmentInfos.FORMAT_HAS_PROX)
Version 1 Int64 同上
NameCounter 1 Int32 同上
SegCount 1 Int32 同上
SegName SegCount String 同上
SegSize SegCount Int32 同上
DelGen SegCount Int64 同上
DocStoreOffset 1 Int32 同上
[DocStoreSegment] 1 String 同上
[DocStoreIsCompoundFile] 1 Int8 同上
HasSingleNormFile SegCount Int8 同上
NumField SegCount Int32 同上
NormGen SegCount * NumField Int64 同上
IsCompoundFile SegCount Int8 同上
DeletionCount SegCount Int32 记录该segment中删除的文档数目
HasProx SegCount Int8 值为1表示该segment中至少一个fieldsomitTf设置为false,否则为0
Checksum 1 Int64 存储segments_N文件中直到checksum的所有字节的CRC32 checksum数据,用来校验打开的索引文件的完整性(integrity)。

   

3.2.2 Lock文件

    

写锁(write lock)文件名为“write.lock”,它缺省存储在索引目录中。如果锁目录(lock directory)与索引目录不一致,写锁将被命名为“XXXX-write.lock”,其中“XXXX”是一个唯一的前缀(unique prefix),来源于(derived from)索引目录的全路径(full path)。当这个写锁出现时,一个writer当前正在修改索引(添加或者清除文档)。这个写锁确保在一个时刻只有一个writer修改索引。

  

需要注意的是在2.1版本之前(prior to),Lucene还使用一个commit lock,这个锁在2.1版本里被删除了。

  

3.2.3 Deletable文件

    

Lucene 2.1版本之前,有一个“deletable”文件,包含了那些需要被删除文档的详细资料。在2.1版本后,一个writer会动态地(dynamically)计算哪些文件需要删除,因此,没有文件被写入文件系统。

           

3.2.4  Compound文件(.cfs

    

Lucene 1.4版本开始,compound文件格式成为缺省信息。这是一个简单的容器(container)来服务所有下一章节(next section)描述的文件(除了.del文件),格式如下:

  

   

版本 包含的项 数目 类型 描述
1.4之后版本 FileCount 1 VInt  
DataOffset FileCount Long  
FileName FileCount String  
FileData FileCount raw Raw文件数据是上面命名的所有单个的文件数据(the individual named above)。

   

结构如下图所示:

    

image012.gif

      

               Annotated Lucene 作者:naven 日期:2008-10-20