海水正蓝

面朝大海,春暖花开
posts - 145, comments - 29, trackbacks - 0, articles - 1
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

工作流管理联盟:

定义:

创建并完善了工作流的相关标准,开拓了相关市场,是唯一的致力于工作流标准化的专业组织。该组织推出了工作流XMLWf-XML)和XML过程定义语言(XPDL) ,现在有超过80种有名的解决方案中使用了这两种语言来存储和交换过程模型。发布了用于工作流管理系统之间互操作的工作流参考模型,并且为了实现不同工作流产品之间的互操作,WfMC在工作流管理系统的相关术语、体系结构及应用编程接口等方面制定了一系列标准

 

工作流:

定义:

工作流是一类能够完全或者部分自动执行的经营过程,根据一系列过程规则,文档、信息或任务能够在不同的执行者之间传递、执行。从工作流的定义可以看出:(1)、有多个参与者:(2)、按照一定的规则进行活动(传递文档、信息、任务等)(3)、活动的推进是自动的或部分自动的。【工作流管理联盟】

 

工作流管理系统:

定义:

工作流管理系统是一个软件系统,它负责工作流的定义和管理,并按照在计算机中预先定义好的工作流逻辑推进过程实例的执行。工作流管理系统(Workflow Management SystemWFMS)是通过对工作流程中涉及各步骤的人员和IT资 源的合理调整,从而起到对工作流的定义、管理和实现的确定性作用。工作流管理系统是支持企业实现业务过程管理和自动化的强有力的软件工具,它能完成工作流 的定义和管理,并按照在计算机中预先定义好的工作流逻辑推进工作流实例的执行。所以工作流是工作流管理系统的最重要的被管理的元素,就像表、试图是数据库 管理系统的管理对象一样。【工作流管理联盟】

 

工作流参考模型:

定义:

1.通用的工作流系统实现模型

2.把工作流系统中的主要功能组件和这些组件间的接口一起看成抽象的模型

 

作用:

1.这个模型可以与市场上的大多数产品相匹配,因此为开发协同工作的工作流系统奠定了基础

2.工作流参考模型的引入为人们讨论工作流技术提供了一一个规范的术语表,为在一般意义上讨论工作流系统的体系结构提供了基础:工作流参考模型为工作流管理系统的关键软件部件提供了功能描述,并描述了关键软件部件交互,而

且这个描述是独立于特定产品或技术的实现的:从功能的角度定义五个关键软件部件的交互接口,推动了信息交换的标准化,使得不同产品间的互操作成为可能。

 

组成:

1.软件组件:为工作流系统的各种功能提供支持。

2.各中类型的系统定义数据和控制数据:系统中的一个或多个软件构件使用的数据。

3.应用程序与应用程序数据库:外部系统或数据,被系统调用来完成整个或部分工作流管理的功能。

 

五类接口(WorkflowAPIWAPI)

接口l:工作流执行服务与工作流建模工具间的接口,为实现对工作流过程定义的访问(如建立、修改、删除等)提供了一致的方法。

接口2:工作流服务和用户应用之间的接口,这是最主要的接口规范,它约定所有客户方应用和工作流服务之间的功能访问方式。

接口3:工作流引擎和应用服务间的直接接口,其目标是集成工作流和其它应用服务而无需考虑原有工作流管理系统。

接口4:工作流管理系统之间的互操作接口,用于描述不同工作流产品的互操作性。

一般必须的互操作有两个主要方面:

(1)流程定义或子集的公共解释;

(2)运行时间对各种控制信息转换,和在不同实施服务之间传递工作流相关数据和应用数据的支持。_个工作流引擎可以选择、实例化和执行其他工作流引擎所约定的流程定义。

接口5:工作流服务和工作流管理工具之间的接口,用于系统管理、应用访问工作流执行服务。

 

通用工作流系统各部分功能:

1.工作流执行服务

工作流执行服务是指由一个或者多个工作流引擎组成,以创建,管理和执行工作流实例,应用程序可能通过工作流应用程序接口(WAPI))与这个服务进行交互。工作流执行服务的主要功能是:解释流程定义,生成过程实例,并管理其实施过程;依据工作流相关数据实现流程活动导航,包括顺序或并行操作、期限设置等;与外部资源交互,完成各项活动;维护工作流控制数据和工作流相关数据,并向用户传送必要的相关数据。

     工作流执行服务使用外部资源的两种途径:

     1.用户应用接口:工作流引擎通过任务项列表管理资源,任务项列表管理器负责从任务项列表中选择并监督工作项的完成。任务项列表管理器或用户负责调用应用工具。

     2.直接调用应用接口:工作流引擎直接调用相应的应用来完成一项任务。这主要是针对基于服务器的无需用户参与的应用,那些需要用户操作的活动则通过任务列表管理器来调用。

 

2.工作流引擎

工作流引擎是指为工作流实例提供运行时执行环境的软件服务或引擎。 主要提供以下功能:对过程定义进行解释;控制过程实例的生成、激活、挂起、终止等;控制过程活动间的转换,包括串行或并行的操作、工作流相关数据的解释 等;支持用户操作的界面;维护工作流控制数据和工作流相关数据,在应用或用户间传递工作流相关数据;提供用于激活外部应用并提供工作流相关数据的界面;提 供控制、管理和监督的功能。

 

3.过程定义工具

过程定义工具是管理流程定义的工具,它可以通过图形方式把复杂的流程定义显示出来并加以操作。流程定义工具同工作流执行服务交互,为用户提供一种对实际业务过程进行分析、建模的手段,并生成业务过程的可被计算机处理的形式化描述(过程定义)。这也是工作流系统建立阶段的主要任务。不同的工作流产品,其建模工具输出格式是不同的。接口l不仅使工作流的定义阶段和运行阶段分离,使用户可以分别选择建模工具和执行产品,并且提供了对工作流过程进行协同定义的潜在能力,这些产品提供了分布的运行服务。

 

4.管理和监控工具

管理和监控工具主要负责对组织机构、角色等数据的维护管理和工作流实例的运行进行监控。管理员可以通过工作流管理工具获得目前各个活动的运行情况报告,并可干预实例的推进。

 

5.客户端应用

客户端应用是通过请求的方式同工作流执行服务交互的应用,也就是说是客户端应用调用工作流执行服务,客户端应用同工作流执行服务交互。它提供给用户一种手段,以处理实例运行过程中需要人工参与的任务。

 

6.调用的应用

调用的应用指工作流执行服务在过程实例运行过程中调用的、用以对应用数据进行处理的应用程序和Web服务

原文出自:
http://www.cnblogs.com/yuziyan/archive/2012/12/08/2809346.html

posted @ 2012-12-10 23:07 小胡子 阅读(213) | 评论 (0)编辑 收藏

类图画法

类之间的几种关系:泛化(Generalization)、实现(Realization)、关联(Association)(又分一般关联、聚合(Aggregation)、组合(Composition))、依赖(Dependency)

一、类图画法

1、  类图的概念

A、显示出类、接口以及它们之间的静态结构和关系

B、用于描述系统的结构化设计

2、  类图的元素

类、接口、协作、关系,我们只简单介绍一下这四种元素。

同其他的图一样,类图也可以包含注解和限制。

类图中也可以包含包和子系统,这两者用来将元素分组。

有时候你也可以将类的实例放到类图中。

3、  类

A、 类是对一组具有相同属性、操作、关系和语义的对象的抽象,它是面向对象系统组织结构的核心,包括名称部分(Name)、属性部分(Attribute)和操作部分(Operation),见下图。

B、 类属性的语法为:

[可见性] 属性名 [:类型] [=初始值] [{属性字符串}]

可见性:公有(Public)“+”、私有(Private)“-”、受保护(Protected)“#”

类操作的语法为:

[可见性] 操作名 [(参数表)] [:返回类型] [{属性字符串}]

可见性:公有(Public)“+”、私有(Private)“-”、受保护(Protected)“#”、包内公有(Package)“~”

参数表:

定义方式:“名称:类型”;若存在多个参数,将各个参数用逗号隔开;参数可以具有默认值;

属性字符串:

在操作的定义中加入一些除了预定义元素之外的信息。

4、  接口

在没有给出对象的实现和状态的情况下对对象行为的描述。

一个类可以实现一个或多个接口。

使用两层矩形框表示,与类图的区别主要是顶端有<<interface>>显示:

也可以用一个空心圆表示:

5、  协作

协作是指一些类、接口和其他的元素一起工作提供一些合作的行为,这些行为不是简单地将元素 加能得到的。例如:当你为一个分布式的系统中的事务处理过程建模型时,你不可能只通过一个类来明白事务是怎样进行的,事实上这个过程的执行涉及到一系列的 类的协同工作。使用类图来可视化这些类和他们的关系。

6、  关系

这篇文章的重点,详见第二部分。

二、类之间的几种关系

1、  泛化(Generalization)

A、 是一种继承关系,表示一般与特殊的关系,它指定了子类如何特化父类的所有特征和行为,描述了一种“is a kind of” 的关系。例如:老虎是动物的一种,即有老虎的特性也有动物的共性。

B、 用带空心箭头的实线表示,箭头指向父类,如下图:

2、  实现(Realization)

A、 是一种类与接口的关系,表示类是接口所有特征和行为的实现。

B、 用带空心箭头的虚线表示,箭头指向接口,如下图:

3、  关联(Association)

A、 一般关联

a、  关联关系是类与类之间的联结,它使一个类知道另一个类的属性和方法,指明了事物的对象之间的联系,如:老师与学生、丈夫与妻子。关联可以是双向的,也可以是单向的,还有自身关联。

b、  用带普通箭头的实心线表示。双向的关联可以有两个箭头或者没有箭头,单向的关联有一个箭头,如下图:

 

B、 聚合(Aggregation)

a、  它是整体与部分(整体 has a 部分)的关系,且部分可以离开整体而单独存在,如车和轮胎是整体和部分的关系,轮胎离开车仍然可以存在。聚合关系是关联关系的一种,是强的关联关系,关联和聚合在语法上无法区分,必须考察具体的逻辑关系。

b、  用带空心菱形的实线表示,菱形指向整体,如下图:

C、 组合(Composition)

a、  它是整体与部分的关系,但部分不能离开整体而单独存在。如公司和部门是整体和部分的关系,没有公司就不存在部门。组合关系是关联关系的一种,是比聚合关系还要强的关系,它要求普通的聚合关系中代表整体的对象负责代表部分的对象的生命周期。

b、  用带实心菱形的实线表示,菱形指向整体,如下图:

4、  依赖(Dependency)

A、 元素A的变化会影响元素B,那么B和A的关系是依赖关系,B依赖A。要避免双向依赖,一般来说,不应该存在双向依赖。关联、实现、泛化都是依赖关系。

B、 用带箭头的虚线表示,箭头指向被依赖元素。

5、  总结

各种关系的强弱顺序如下:

泛化 = 实现 > 组合 > 聚合 > 关联 > 依赖

下面这张UML图,比较形象地展现了各种类图关系:

原文出自:
http://www.cnblogs.com/fuhongxue2011/archive/2012/12/09/2810408.html

posted @ 2012-12-10 21:50 小胡子 阅读(939) | 评论 (0)编辑 收藏

     摘要: 近日来对Ext特别感兴趣,也许是它那种OO的设计思想吸引了我,也可以追溯到第一次见到EXT那种漂亮的界面开始吧.求神拜佛不如自食其力,为了一点小的问题找遍了GOOGLE也没个结果,自己甚少去BBS混,也不熟悉规矩,只能硬着头皮自己干了.翻源代码是一道必不可少的工序,说来惭愧,自己对JS的认识还停留在入门阶段.这里说说自己对于Ext验证这里浅薄的理解:首先看看如下一段代码Code highlight...  阅读全文

posted @ 2012-12-08 23:19 小胡子 阅读(704) | 评论 (0)编辑 收藏

由于HTTP协议的无状态特性,导致在ASP.NET编程中,每个请求都会在服务端从头到执行一次管线过程, 对于ASP.NET页面来说,Page对象都会重新创建,所有控件以及内容都会重新生成, 因此,如果希望上一次的页面状态能够在后续页面中保留,则必需引入状态管理功能。

ASP.NET为了实现状态管理功能,提供了8种方法,可帮助我们在页面之间或者整个用户会话期间保留状态数据。 这些方法分为二类:视图状态、控件状态、隐藏域、Cookie 和查询字符串会以不同方式将数据发送到客户端上。 而应用程序状态、会话状态和配置文件属性(Profile)则会将数据存储到服务端。 虽然每种方法都有不同的优点和缺点,对于小的项目来说,可以选择自己认为最容易使用的方法, 然而,对于有着较高要求的程序,尤其是对于性能与扩展性比较关注的程序来说, 选择不同的方法最终导致的差别可能就非常大了。

在这篇博客中,我将谈谈自己对ASP.NET状态管理方面的一些看法。
注意:本文的观点可能并不合适开发小型项目,因为我关注的不是易用性。

hidden-input

hidden-input 这个名字我是取的,表示所有type="hidden"的input标签元素。 在中文版的MSDN中,也称之为 隐藏域 。 hidden-input通常存在于HTML表单之内,它不会显示到页面中, 但可以随表单一起提交,因此,经常用于维护当前页面的相关状态,在服务端我们可以使用Request.Form[]来访问这些数据。

一般说来,我通常使用hidden-input来保存一些中间结果,用于在多次提交中维持一系列状态, 或者用它来保存一些固定参数用来提交给其它页面(或网站)。 在这些场景中,我不希望用户看到这些数据,因此,使用hidden-input是比较方便的。

关于表单的更多介绍可参考我的博客:细说 Form (表单)

在ASP.NET WebForm框架中,我们可以使用HiddenField控件来创建一个hidden-input控件,并可以在服务端操作它, 还可以直接以手写的方式使用隐藏域,例如:

<input type="hidden" name="hidden-1" value="aaaaaaa" /> <input type="hidden" name="hidden-2" value="bbbbbbb" /> <input type="hidden" name="hidden-3" value="ccccccc" /> 

另外,我们还可以调用ClientScript.RegisterHiddenField()方法来创建隐藏域:

ClientScript.RegisterHiddenField("hidden-4", "ddddddddd"); 

输出结果:

<input type="hidden" name="hidden-4" id="hidden-4" value="ddddddddd" /> 

这三种方法对于生成的HTML代码来说,主要差别在于它们出现位置不同:
1. HiddenField控件:由HiddenField的出现位置来决定(在form内部)。
2. RegisterHiddenField方法:在form标签的开头位置。
3. hidden-input:你写在哪里就是哪里。

优点:
1. 不需要任何服务器资源:隐藏域随页面一起发送到客户端。
2. 广泛的支持:几乎所有浏览器和客户端设备都支持具有隐藏域的表单。
3. 实现简单:隐藏域是标准的 HTML 控件,不需要复杂的编程逻辑。

缺点:
1. 不能在多页面跳转之间维持状态。
2. 用户可见,保存敏感数据时需要加密。

QueryString

查询字符串是存在于 URL 结尾的一段数据。下面是一个典型的查询字符串示例(红色部分文字):

http://www.abc.com/demo.aspx?k1=aaa&k2=bbb&k3=ccc 

查询字符串经常用于页面的数据过滤,例如:
1. 给列表页面增加分页参数,list.aspx?page=2
2. 给列表页面增加过虑范围,Product.aspx?categoryId=5
3. 显示特定记录,ProductInfo.aspx?page=3

关于查询字符串的用法,我补充二点:
1. 可以调用HttpUtility.ParseQueryString()来解析查询字符串。
2. 允许参数名重复:list.aspx?page=2&page=3,因此在修改URL参数时,使用替换方式而不是追加。
  关于参数重名的读取问题,请参考我的博客:细说 Request[]与Request.Params[]

优点:
1. 不需要任何服务器资源:查询字符串的数据包含在每个URL中。
2. 广泛的支持:几乎所有的浏览器和客户端设备均支持使用查询字符串传递参数值。
3. 实现简单:在服务端直接访问Request.QueryString[]可读取数据。
4. 页面传值简单:<a href="url">或者 Response.Redirect(url) 都可以实现。

缺点:
1. 有长度限制。
2. 用户可见,不能保存敏感数据。

Cookie

由于HTTP协议是无状态的,对于一个浏览器发出的多次请求,WEB服务器无法区分它们是不是来源于同一个浏览器。所以,需要额外的数据用于维护会话。 Cookie 正是这样的一段随HTTP请求一起被传递的额外数据。 Cookie 是一小段文本信息,它的工作方式就是伴随着用户请求和页面在 Web 服务器和浏览器之间传递。Cookie 包含每次用户访问站点时 Web 应用程序都可以读取的信息。

与hidden-input, QueryString相比,Cookie有更多的属性,许多浏览器可以直接查看这些信息:

由于Cookie拥有这些属性,因此在客户端状态管理中可以实现更多的功能,尤其是在实现客户端会话方面具有不可替代的作用。

关于Cookie的更多讲解,请参考我的另一篇博客:细说Cookie

优点:
1. 可配置到期规则:Cookie可以在客户端长期存在,也可以在浏览器关闭时清除。
2. 不需要任何服务器资源:Cookie 存储在客户端。
3. 简单性:Cookie 是一种基于文本的轻量结构,包含简单的键值对。
4. 数据持久性:与其它的客户端状态数据相比,Cookie可以实现长久保存。
5. 良好的扩展性:Cookie的读写要经过ASP.NET管线,拥有无限的扩展性。

这里我要解释一下Cookie 【良好的扩展性】是个什么概念,比如:
1. 我可以实现把Cookie保存到数据库中而不需要修改现有的项目代码。
2. 把SessionId这样由ASP.NET产生的临时Cookie让它变成持久保存。

缺点:
1. 大小受到限制。
2. 增加请求头长度。
3. 用户可见,保存敏感数据时需要加密。

ApplicationState

应用程序状态是指采用HttpApplicationState实现的状态维持方式,使用代码如下:

Application.Lock(); Application["PageRequestCount"] = ((int)Application["PageRequestCount"]) + 1; Application.UnLock(); 

对于这种方法,我不建议使用,因为:
1. 与使用静态变量差不多,直接使用静态变量可以不需要字典查找。
2. 选择强类型的集合或者变量可以避免装箱拆箱。

ViewState,ControlState

视图状态,控件状态,二者是类似,在页面中表现为一个hidden-input元素:

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="......................" /> 

控件状态是ASP.NET 2.0中引入,与视图状态相比,它不允许关闭。
由于它们使用方式一致,而且视图状态是基于控件状态的实现逻辑,所以我就不区分它们了。

在ASP.NET的早期,微软为了能帮助广大开发人员提高开发效率,引用入一大批的服务端控件,并为了能将事件编程机制引入ASP.NET中,又发明了ViewState。

这种方式虽然可以简化开发工作量,然而却有一些限制和缺点:
1. 视图状态的数据只能用于回发(postback)。
2. 视图状态的【滥用】容易导致生成的HTML较大,这会引起一个恶性循环:
  a. 过大的ViewState在序列化过程中会消耗较多的服务器CPU资源,
  b. 过大的ViewState最终生成的HTML输出也会很大,它会浪费服务端网络资源,
  c. 过大的ViewState输出导致表单在下次提交时,会占用客户端网络资源。
  d. 过大的ViewState数据上传到服务端后,反序列化又会消耗较多的服务器CPU资源。
  因此,整个交互过程中,用户一直在等待,用户体验极差。

在ASP.NET兴起的年代,ViewState绝对是个了不起的发明。
然而,现在很多关于ASP.NET性能优化的方法中,都会将【关闭ViewState】放在头条位置。
为什么会这样呢,大家可以自己思考一下了。

有些人认为:我现在做的程序只是在局域网内使用,使用ViewState完全没有问题!
然而,那些人或许没有想过:
1. 未来用户可能会把它部署在互联网上运行(对于产品来说就是遇到大客户了)。
2. 项目早期的设计与规划,对后期的开发与维护来说,影响是巨大的,因为许多基础部分通常是在早期开发的。
当这二种情况的任何一种发生时,想再禁用ViewState,可能已经晚了。

对于视图状态,我认为它解决的问题比它引入的问题要多要复杂,
因此,我不想花时间整理它的优缺点,我只想说一句:把它关了,在web.config中关了。

另外,我不排斥使用服务器控件,我认为:你可以使用服务端控件显示数据,但不要用它处理回发。

如果你仍然认为视图状态是不可缺少的,那我还是建议你看看ASP.NET MVC框架,看看没有视图状态是不是照样可以写ASP.NET程序。

Session

Session是ASP.NET实现的一种服务端会话技术,它允许我们方便地在服务端保存与用户有关的会话数据。

我认为Session只有一个优点:最简单的服务端会话实现方式。

缺点:
1. 当mode="InProc"时,容易丢失数据,为什么?因为网站会因为各种原因重启。
2. 当mode="InProc"时,Session保存的东西越多,就越占用服务器内存,对于用户在线人数较多的网站,服务器的内存压力会比较大。
3. 当mode="InProc"时,程序的扩展性会受到影响,原因很简单:服务器的内存不能在多台服务器间共享。
4. 当采用进程外模式时,在每次请求中,不管你用不用会话数据,所有的会话数据都为你准备好了(反序列化),这其实很是浪费资源的。
5. 如果你没有关闭Session,SessionStateModule就一直在工作中,尤其是全采用默认设置时,会对每个请求执行一系列的调用,浪费资源。
6. 阻塞同一客户端发起的多次请求(默认方式)。
7. 无Cookie会话可能会丢失数据(重新生成已过期的会话标识符)。

Session的这些缺点也提醒我们:
1. 当网站的在线人数较多时,一定不要用Session保存较大的对象。
2. 在密集型的AJAX型网站或者大量使用iframe的网站中,要关注Session可能引起的服务端阻塞问题。
3. 当采用进程外模式时,不需要访问Session的页面,一定要关闭,否则会浪费服务器资源。

如果想了解更多的Session特点,以及我对Session的看法,可以浏览我的博客:Session,有没有必要使用它?

Session的本质有二点:
1. SessionId + 服务端字典:服务端字典保存了某个用户的所有会话数据。
2. 用SessionId识别不同的客户端:SessionId通常以Cookie形式发送到客户端。

我认为了解Sesssion本质非常有用,因为可以借鉴并实现自己的服务端会话方法。

关于Session我还想说一点:
有些新手喜欢用Session来实现身份认证功能,这是一种【不正确】的方法。
如果你的ASP.NET应用程序需要身份认证功能,请使用 Forms身份认证 或者 Windows身份认证

Profile

Profile 在中文版的MSDN中被称为 配置文件属性,这个功能是在 ASP.NET 2.0 中引入的。

ASP.NET提供这个功能主要是为了简化与用户相关的个性化信息的读写方式。
简化主要体现在3个方面:
1. 自动与某个用户关联,已登录用户或者未登录都支持。
2. 不需要我们设计用户的个性化信息的保存表结构,只要修改配置文件就够了。
3. 不需要我们实现数据的加载与保存逻辑,ASP.NET框架替我们实现好了。

为了使用Profile,我们首先在web.config中定义所需要的用户个性化信息:

<profile>     <properties>         <add name="Address"/>         <add name="Tel"/>     </properties> </profile> 

然后,就可以在页面中使用了:

为什么会这样呢?
原因是ASP.NET已经根据web.config为我们创建了一个新类型:

using System; using System.Web.Profile;  public class ProfileCommon : ProfileBase {     public ProfileCommon();      public virtual string Address { get; set; }     public virtual string Tel { get; set; }      public virtual ProfileCommon GetProfile(string username); } 

有了这个类型后,当我们访问HttpContext.Profile属性时,ASP.NET会创建一个ProfileCommon的实例。 也正是由于Profile的强类型机制,在使用Profile时才会有智能提示功能。

如果我们希望为未登录的匿名用户也提供这种支持,需要将配置修改成:

<profile>     <properties>         <add name="Address" allowAnonymous="true" />         <add name="Tel" allowAnonymous="true"/>     </properties> </profile> <anonymousIdentification enabled="true" /> 

Profile中的每个属性还允许指定类型和默认值,以及序列化方式,因此,扩展性还是比较好的。

尽管Profile看上去很美,然而,使用Profile的人却很少。
比如我就不用它,我也没见有人有过它。
为什么会这样?

我个人认为:它与MemberShip一样,是个鸡肋。
通常说来,我们会为用户信息创建一张User表,增加用户信息时,会通过增加字段的方式解决。
我认为这样集中的数据才会更好,而不是说,有一部分数据由我维护,另一部分数据由ASP.NET维护。

另一个特例是:我们根本不创建User表,直接使用MemberShip,那么Profile用来保存MemberShip没有信息是有必要的。

还是给Profile做个总结吧:
优点:使用简单。
缺点:不实用。

各种状态管理的对比与总结

前面分别介绍了ASP.NET的8种状态管理技术,这里打算给它们做个总结。


客户端 服务端
数据安全性
数据长度限制 受硬件限制
占用服务器资源
集群扩展性

表格中主要考察了数据保存与服务端水平扩展的相关重要指标。

下面我来解释表格的结果。
1. 客户端方式的状态数据(hidden-input, QueryString, Cookie):
  a. 数据对用户来说,可见可修改,因此数据不安全。
  b. QueryString, Cookie 都有长度限制。
  c. 数据在客户端,因此不占用服务端资源。这个特性对于在线人数很多的网站非常重要。
  d. 数据在客户端,因此和服务端没有耦合关系,WEB服务器可以更容易实现水平扩展。

2. 服务端方式的状态数据(ApplicationState,ViewState,ControlState,Session,Profile):
  a. 数据对用户不可见,因此安全性好。(ApplicationState,Session,Profile)
  b. 数所长度只受硬件限制,因此,对于在线人数较多的网站,需谨慎选择。
  c. 对于存放在内存中的状态数据,由于不能共享内存,因此会限制水平扩展能力。
  d. 如果状态数据保存到一台机器,会有单点失败的可能,也会限制了水平扩展能力。

从这个表格我们还可以得到以下结论:
1. 如果很关注数据的安全性,应该首选服务端的状态管理方法。
2. 如果你关注服务端的水平扩展性,应该首选客户端的状态管理方法。

会话状态的选择

接下来,我们再来看看会话状态,它与状态管理有着一些关系,属于比较类似的概念。

谈到会话状态,首先我要申明一点:会话状态与状态不是一回事。

本文前面所说的状态分为二种:
1. 页面之间的状态。
2. 应用程序范围内的状态。

而会话状态是针对某个用户来说,他(她)在多次操作之间的状态。
在用户的操作期间,有可能状态需要在页面之间持续使用,
也有可能服务端程序做过重启,但数据仍然有效。
因此,这种状态数据更持久。

在ASP.NET中,使用会话状态有二个选择:Session 或者 Cookie 。
前者由ASP.NET实现,并有可能依赖后者。
后者则由浏览器实现,ASP.NET提供读写方法。

那么到底选择哪个呢?
如果你要问我这个问题,我肯定会说:我选 Cookie !

下面是我选择Cookie实现会话状态的理由:
1. 不会有服务端阻塞问题。
2. 不占用服务端资源。
3. 水平扩展没有限制。
4. 也支持过期设置,而且更灵活。
5. 可以在客户端直接使用会话数据。
6. 可以实现更灵活的会话数据加载策略。
7. 扩展性较好(源于ASP.NET管线的扩展性)

如果选择使用Cookie实现会话状态,有3点需要特别注意:
1. 不建议保存敏感数据,除非已加密。
2. 只适合保存短小简单的数据。
3. 如果会话数据较大,可以在客户端保存用户标识,由服务端实现数据的加载保存逻辑。

或许有些人认为:每种技术都有它们的优缺点,有各自的适用领域。
我表示赞同这句话。
但是,我们要清楚一点:每个项目的规模不一样,性能以及扩展性要求也不同。
对于一个小的项目来说,选择什么方法都不是问题,
但是,对于规模较大的项目,我们一定需要取舍。
取舍的目标是:包装越少越好,因为人家做了过多的包装,就会有较多的限制,
所以,不要只关注现在的调用是否方便,其实只要你愿意包装,你也可以让复杂的调用简单化。

改变开发方式,发现新方法

回想一下:为什么在ASP.NET中需要状态管理?
答:因为与HTTP协议有关,服务端没有保存每个请求的上次页面状态。

为什么Windows计算器(这类)程序不用考虑会话问题呢?
答:因为这类程序的界面不需要重新生成,任何变量都可表示状态。

再来看这样一个场景:

图片左边是一个列表页面,允许调整每条记录的优先级,但是有2个要求:
1. 在移动每条记录时,必须输入一个调整理由。
2. 只要输入理由后,那条记录可以任意调整多次。

显然,完成这个任务必须要有状态才能实现。

面对这个问题,你可以思考一下:选择哪种ASP.NET支持的状态管理方法都很麻烦。

怎么办?

我的解决方法:创建一个JavaScript数组,用每个数组元素保存每条记录的状态,
所有用户交互操作用AJAX方式实现,这样页面不会刷新,JavaScript变量中的状态一直有效。
因此,很容易就能解决这个问题。

这个案例也提醒我们:当发现ASP.NET提供的状态管理功能全部不合适时, 我们需要改变开发方式了。

为什么WEB编程都有【无状态】问题,而桌面程序没有?
我认为与HTTP协议有关,但没有绝对的关系。
只要你能保证页面不刷新,也能像桌面程序那样,用JavaScript变量就能维护页面状态。

原文出自:
http://www.cnblogs.com/fish-li/archive/2012/11/21/2780086.html

posted @ 2012-12-08 17:44 小胡子 阅读(248) | 评论 (0)编辑 收藏

1.本地库导出

mysqldump 
-u 用户名 -p 数据库名 > 存放位置
例: mysqldump 
-uroot -p1234 testdb > /root/db/testdb.sql


2.从远程库导出

mysqldump 
-h 主机IP -u 用户名 -p 数据库名 > 存放位置
例: mysqldump 
-h192.168.30.30 -uroot -p1234 testdb > /root/db/testdb.sql


3.导出表结构及数据

mysqldump 
-u 用户名 -p 数据库名 表名 > 导出的文件名
例: mysqldump 
-uroot -p1234 testdb tab > /root/db/testdb.tab.sql


4.导入数据库

mysql 
-u用户名 -p密码 数据库名 < 数据库名
例: mysql 
-uroot -p1234 testdb < /root/db/back.sql
注意:testdb 要事先创建好.


原文出自:
http://www.cnblogs.com/natgeo/archive/2012/12/08/2809027.html
















posted @ 2012-12-08 17:07 小胡子 阅读(189) | 评论 (0)编辑 收藏

在formPanel里加个Key事件

 1  keys : [{
 2       key : Ext.EventObject.ENTER,
 3       fn : function(keyCode, e) {
 4        var field = Ext.getCmp(e.target.id);
 5        if (Ext.isDefined(field) && field != null) {
 6         if (Ext.isDefined(field.xtype)) {
 7          if (field.isXType('datefield')) {
 8           field.setValue(field.getValue());
 9          }
10         }
11        }
12        if (Ext.isIE) {
13         e.browserEvent.keyCode = Ext.EventObject.TAB;
14        } else {
15         var currentfield = Ext.getCmp(e.target.id);
16         var fields = refThis.HusbandView
17           .findByType('field');
18         var i = 0;
19         for (; i < fields.length; i++) {
20          if (fields[i].id == currentfield.id)
21           break;
22         }
23         while (true) {
24          i++;
25          if (fields.length <= i)
26           break;
27          if (!fields[i].disabled
28            && fields[i].xtype != 'hidden'
29            && !fields[i].hidden)
30           break;
31         }
32         if (fields.length <= i)
33          return;
34         if (!fields[i].disabled) {
35          fields[i].focus();
36          if (Ext.isDefined(fields[i].selectText))
37           fields[i].selectText();
38         }
39        }
40       }
41      }]

原文出自:
http://xlong224.blog.163.com/blog/static/601214932011102810201224/

posted @ 2012-12-06 23:16 小胡子 阅读(395) | 评论 (0)编辑 收藏

原先的EditGrid无法解决回车控制问题,它的回车控制是向下跑的。而我想让它横着走。搞了半天终于实现了。

 1 Ext.override(Ext.grid.RowSelectionModel, {
 2                 onEditorKey : function(field, e) {
 3                     // alert('go');
 4                     var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
 5                     var shift = e.shiftKey;
 6                     Ext.log('k:' + k);
 7                     if (k == e.ENTER) {
 8                         e.stopEvent();
 9                         ed.completeEdit();
10                         if (shift) {
11                             newCell = g.walkCells(ed.row, ed.col - 1-1,
12                                     this.acceptsNav, this);
13                         } else {
14                             // alert('go');
15                             newCell = g.walkCells(ed.row, ed.col + 11,
16                                     this.acceptsNav, this);
17                         }
18                     } else if (k == e.TAB) {
19                         e.stopEvent();
20                         ed.completeEdit();
21                         if (this.moveEditorOnEnter !== false) {
22                             if (shift) {
23                                 newCell = g.walkCells(ed.row - 1, ed.col, -1,
24                                         this.acceptsNav, this);
25                             } else {
26                                 // alert('go');
27                                 newCell = g.walkCells(ed.row + 1, ed.col, 1,
28                                         this.acceptsNav, this);
29                             }
30                         }
31                     } else if (k == e.ESC) {
32                         ed.cancelEdit();
33                     }
34                     if (newCell) {
35                         g.startEditing(newCell[0], newCell[1]);
36                     }
37                 }
38             });
39     var sm2 = new Ext.grid.RowSelectionModel({
40         moveEditorOnEnter : true,
41         singleSelect : true,
42         listeners : {
43             rowselect : function(sm, row, rec) {
44                 centerForm.getForm().loadRecord(rec);
45             }
46         }
47 
48     });

原文出自:
http://erichua.iteye.com/blog/234698

2.

默认extjs中editorgrid编辑单元格的时候按回车是将焦点向下移动,按照一般的逻辑应该是向右移动。

其实只要将原先rowSelectionModel中onEditorKey方法override一下即可。

代码如下:


 1 Ext.override(Ext.grid.RowSelectionModel, {
 2 
 3  onEditorKey : function(field, e) {
 4   var k = e.getKey(), newCell, g = this.grid, last = g.lastEdit, ed = g.activeEditor, shift = e.shiftKey, ae, last, r, c;
 5 
 6   if (k == e.TAB) {
 7    e.stopEvent();
 8    ed.completeEdit();
 9    if (shift) {
10     newCell = g.walkCells(ed.row, ed.col - 1-1this.acceptsNav,
11       this);
12    } else {
13     newCell = g.walkCells(ed.row, ed.col + 11this.acceptsNav,
14       this);
15    }
16   } else if (k == e.ENTER) {
17    if (this.moveEditorOnEnter !== false) {
18     if (shift) {
19      newCell = g.walkCells(last.row, last.col - 1-1,
20        this.acceptsNav, this);
21     } else {
22      newCell = g.walkCells(last.row, last.col + 11,
23        this.acceptsNav, this);
24     }
25    }
26   }
27   if (newCell) {
28    r = newCell[0];
29    c = newCell[1];
30 
31    this.onEditorSelect(r, last.row);
32 
33    if (g.isEditor && g.editing) { // *** handle tabbing while
34            // editorgrid is in edit mode
35     ae = g.activeEditor;
36     if (ae && ae.field.triggerBlur) {
37      // *** if activeEditor is a TriggerField, explicitly call
38      // its triggerBlur() method
39      ae.field.triggerBlur();
40     }
41    }
42    g.startEditing(r, c);
43   }
44  }
45 })

 

posted @ 2012-12-06 23:14 小胡子 阅读(2206) | 评论 (0)编辑 收藏

方法1: JMX

很多人询问如何通过 JMX 来管理 Quertz,很奇怪的是 Quartz 的文档完全没有提及这方面的问题,你可以在 quartz.properties 中通过以下配置来启用 JMX 的支持:

org.quartz.scheduler.jmx.export = true

然后你就可以使用标准的 JMX 客户端,例如 $JAVA_HOME/bin/jconsole 来连接到 Quartz 并进行远程管理。

方法2: RMI

另外一个远程管理 Quartz 的方法就是启用 RMI。如果你用的是 RMI 的方式,就会自动一个 Quartz 实例来作为 RMI 服务器,然后你可启动第二个 Quartz 实例来作为 RMI 客户端,二者通过 TCP 端口进行通讯。

服务器端调度实例配置方法(quartz.properties):

org.quartz.scheduler.rmi.export = true
org.quartz.scheduler.rmi.createRegistry 
= true
org.quartz.scheduler.rmi.registryHost 
= localhost
org.quartz.scheduler.rmi.registryPort 
= 1099
org.quartz.scheduler.rmi.serverPort 
= 1100

客户端调度器配置(quartz.properties):

org.quartz.scheduler.rmi.proxy = true
org.quartz.scheduler.rmi.registryHost 
= localhost
org.quartz.scheduler.rmi.registryPort 
= 1099

关于 Quartz 的 RMI 特性的文档描述请看 这里. Quartz 不提供客户端 API,服务器端和客户端都是使用 org.quartz.Scheduler,只是配置不同而已。通过不同的配置来执行不同的行为。对服务器端来说,调度器用来执行所有的作业;而客户端只 是一个简单的代理,不运行任何作业,在关闭客户端的时候必须小心,因为它允许你也同时关闭服务器端。

这些配置都在我的示例程序 MySchedule 中有着重说明,如果你运行的是 Web 应用,你可以看到 这个演示,你将看到我们提供了很多 quartz 的示例配置用来做远程管理。

如果使用 RMI 方法,你可以用 MySchedule Web UI 做为一个代理来管理 Quartz,你可以查看作业,可停止服务器的运行。

根据我的经验,使用 RMI 方法的弊端就是创建一个新的单点故障,如果你的服务器端口宕掉了,就无法恢复。

原文出自:

http://www.oschina.net/question/12_67413

posted @ 2012-12-04 12:36 小胡子 阅读(837) | 评论 (0)编辑 收藏

1、Scheduler的配置

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="testTrigger"/>
</list>
</property>
<property name="autoStartup" value="true"/>
</bean> 
    说明:Scheduler包含一个Trigger列表,每个Trigger表示一个作业。

2、Trigger的配置

<bean id="testTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="testJobDetail"/>
<property name="cronExpression" value="*/1 * * * * ?"/>
<!-- 每隔1秒钟触发一次 -->
</bean> 
    说明:

         1)Cron表达式的格式:秒 分 时 日 月 周 年(可选)。

               字段名                 允许的值                        允许的特殊字符  

               秒                         0-59                               , - * /  

               分                         0-59                               , - * /  

               小时                   0-23                               , - * /  

               日                         1-31                               , - * ? / L W C  

               月                         1-12 or JAN-DEC          , - * /  

               周几                     1-7 or SUN-SAT            , - * ? / L C #  

               年 (可选字段)     empty, 1970-2099      , - * /

               “?”字符:表示不确定的值

               “,”字符:指定数个值

               “-”字符:指定一个值的范围

               “/”字符:指定一个值的增加幅度。n/m表示从n开始,每次增加m

               “L”字符:用在日表示一个月中的最后一天,用在周表示该月最后一个星期X

               “W”字符:指定离给定日期最近的工作日(周一到周五)

               “#”字符:表示该月第几个周X。6#3表示该月第3个周五

         2)Cron表达式范例:

                 每隔5秒执行一次:*/5 * * * * ?

                 每隔1分钟执行一次:0 */1 * * * ?

                 每天23点执行一次:0 0 23 * * ?

                 每天凌晨1点执行一次:0 0 1 * * ?

                 每月1号凌晨1点执行一次:0 0 1 1 * ?

                 每月最后一天23点执行一次:0 0 23 L * ?

                 每周星期天凌晨1点实行一次:0 0 1 ? * L

                 在26分、29分、33分执行一次:0 26,29,33 * * * ?

                 每天的0点、13点、18点、21点都执行一次:0 0 0,13,18,21 * * ?

3、JobDetail的配置

<bean id="testJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="testJob"/>
<property name="targetMethod" value="execute"/>
<property name="concurrent" value="false"/>
<!-- 是否允许任务并发执行。当值为false时,表示必须等到前一个线程处理完毕后才再启一个新的线程 -->
</bean> 
4、业务类的配置

<bean id="testJob" class="com.cjm.web.service.quartz.TestJob"/>  

5、业务类源代码

public class TestJob { 
 
public void execute(){ 
   
try{                 
       
//.          
      }catch(Exception ex){
       ex.printStackTrace();
       }
     }
   } 
    说明:业务类不需要继承任何父类,也不需要实现任何接口,只是一个普通的java类。

注意:

     在Spring配置和Quartz集成内容时,有两点需要注意

           1、在<Beans>中不能够设置default-lazy-init="true",否则定时任务不触发,如果不明确指明default-lazy-init的值,默认是false。

           2、在<Beans>中不能够设置default-autowire="byName"的属性,否则后台会报 org.springframework.beans.factory.BeanCreationException错误,这样就不能通过Bean名称自 动注入,必须通过明确引用注入


原文出自:

http://www.oschina.net/question/8676_9032

posted @ 2012-12-04 12:25 小胡子 阅读(355) | 评论 (0)编辑 收藏

缓存在 Solr 中充当了一个非常重要的角色,Solr 中主要有这三种缓存:
  • Filter cache(过滤器缓存),用于保存过滤器(fq 参数)和层面搜索的结果
  • Document cache(文档缓存),用于保存 lucene 文档存储的字段
  • Query result(查询缓存),用于保存查询的结果
还有第四种缓存,lucene 内部的缓存,不过该缓存外部无法控制到。

通过这 3 种缓存,可以对 solr 的搜索实例进行调优。调整这些缓存,需要根据索引库中文档的数量,每次查询结果的条数等。
在调整参数前,需要事先得到 solr 示例中的以下信息:
  • 索引中文档的数量
  • 每秒钟搜索的次数
  • 过滤器的数量
  • 一次查询返回最大的文档数量
  • 不同查询和不同排序的个数
这些数量可以在 solr admin 页面的日志模块找到。假设以上的值分别为:

  • 索引中文档的数量:1000000
  • 每秒钟搜索的次数:100
  • 过滤器的数量:200
  • 一次查询返回最大的文档数量:100
  • 不同查询和不同排序的个数:500
然后可以开始修改 solrconfig.xml 中缓存的配置了,第一个是过滤器缓存:

<filterCache class="solr.FastLRUCache" size="200" initialSize="200"  autowarmCount="100"/>
第二个是查询结果缓存:

<queryResultCache class="solr.FastLRUCache" size="500" initialSize="500" autowarmCount="250"/>
第三个是文档缓存:

<documentCache class="solr.FastLRUCache" size="11000" initialSize="11000" />
这几个配置是基于以上的几个假设的值进行调优的。
原文出自:
http://insolr.com/forum.php?mod=viewthread&tid=7&reltid=880&pre_thread_id=19&pre_pos=5&ext=

posted @ 2012-12-03 16:54 小胡子 阅读(1546) | 评论 (0)编辑 收藏

仅列出标题
共15页: First 上一页 3 4 5 6 7 8 9 10 11 下一页 Last