2011年6月22日
摘要: 一、分布式实现原理
如上图所示,主要通过Apache-Server作为中转服务器,实现多个tomcat服务器之间的分布式处理,用户直接请求Apache-Server,然后Apache-Server会将请求分发到具体的tomcat-server,之...
阅读全文
posted @
2011-06-22 16:09 obpm 阅读(8197) |
评论 (4) |
编辑 收藏
2010年11月7日
从设计理念层面看abstract class和interface
上面主要从语法定义和编程的角度论述了abstract class和interface的区别,这些层面的区别是比较低层次的、非本质的。本小节将从另一个层面:abstract class和interface所反映出的设计理念,来分析一下二者的区别。作者认为,从这个层面进行分析才能理解二者概念的本质所在。
前面已经提到过,abstarct class在Java语言中体现了一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在"is a"关系,即父类和派生类在概念本质上应该是相同的(参考文献〔3〕中有关于"is a"关系的大篇幅深入的论述,有兴趣的读者可以参考)。对于interface 来说则不然,并不要求interface的实现者和interface定义在概念本质上是一致的,仅仅是实现了interface定义的契约而已。为了使论述便于理解,下面将通过一个简单的实例进行说明。
考虑这样一个例子,假设在我们的问题领域中有一个关于Door的抽象概念,该Door具有执行两个动作open和close,此时我们可以通过abstract class或者interface来定义一个表示该抽象概念的类型,定义方式分别如下所示:
使用abstract class方式定义Door:
abstract class Door {
abstract void open();
abstract void close();
}
使用interface方式定义Door:
interface Door {
void open();
void close();
}
其他具体的Door类型可以extends使用abstract class方式定义的Door或者implements使用interface方式定义的Door。看起来好像使用abstract class和interface没有大的区别。
如果现在要求Door还要具有报警的功能。我们该如何设计针对该例子的类结构呢(在本例中,主要是为了展示abstract class和interface反映在设计理念上的区别,其他方面无关的问题都做了简化或者忽略)?下面将罗列出可能的解决方案,并从设计理念层面对这些不同的方案进行分析。
解决方案一:
简单的在Door的定义中增加一个alarm方法,如下:
abstract class Door {
abstract void open();
abstract void close();
abstract void alarm();
}
或者
interface Door {
void open();
void close();
void alarm();
}
那么具有报警功能的AlarmDoor的定义方式如下:
class AlarmDoor extends Door {
void open() { … }
void close() { … }
void alarm() { … }
}
或者
class AlarmDoor implements Door {
void open() { … }
void close() { … }
void alarm() { … }
}
这种方法违反了面向对象设计中的一个核心原则ISP(Interface Segregation Priciple),在Door的定义中把Door概念本身固有的行为方法和另外一个概念"报警器"的行为方法混在了一起。这样引起的一个问题是那些仅仅依赖于Door这个概念的模块会因为"报警器"这个概念的改变(比如:修改alarm方法的参数)而改变,反之依然。
解决方案二:
既然open、close和alarm属于两个不同的概念,根据ISP原则应该把它们分别定义在代表这两个概念的抽象类中。定义方式有:这两个概念都使用abstract class方式定义;两个概念都使用interface方式定义;一个概念使用abstract class方式定义,另一个概念使用interface方式定义。
显然,由于Java语言不支持多重继承,所以两个概念都使用abstract class方式定义是不可行的。后面两种方式都是可行的,但是对于它们的选择却反映出对于问题领域中的概念本质的理解、对于设计意图的反映是否正确、合理。我们一一来分析、说明。
如果两个概念都使用interface方式来定义,那么就反映出两个问题:1、我们可能没有理解清楚问题领域,AlarmDoor在概念本质上到底是Door还是报警器?2、如果我们对于问题领域的理解没有问题,比如:我们通过对于问题领域的分析发现AlarmDoor在概念本质上和Door是一致的,那么我们在实现时就没有能够正确的揭示我们的设计意图,因为在这两个概念的定义上(均使用interface方式定义)反映不出上述含义。
如果我们对于问题领域的理解是:AlarmDoor在概念本质上是Door,同时它有具有报警的功能。我们该如何来设计、实现来明确的反映出我们的意思呢?前面已经说过,abstract class在Java语言中表示一种继承关系,而继承关系在本质上是"is a"关系。所以对于Door这个概念,我们应该使用abstarct class方式来定义。另外,AlarmDoor又具有报警功能,说明它又能够完成报警概念中定义的行为,所以报警概念可以通过interface方式定义。如下所示:
abstract class Door {
abstract void open();
abstract void close();
}
interface Alarm {
void alarm();
}
class AlarmDoor extends Door implements Alarm {
void open() { … }
void close() { … }
void alarm() { … }
}
这种实现方式基本上能够明确的反映出我们对于问题领域的理解,正确的揭示我们的设计意图。其实abstract class表示的是"is a"关系,interface表示的是"like a"关系,大家在选择时可以作为一个依据,当然这是建立在对问题领域的理解上的,比如:如果我们认为AlarmDoor在概念本质上是报警器,同时又具有Door的功能,那么上述的定义方式就要反过来了。
转载人员-Nicholas
posted @
2010-11-07 13:57 obpm 阅读(552) |
评论 (4) |
编辑 收藏
2010年10月24日
可关闭的TabbedPane结构:
测试代码:
package cn.demo.test;
import java.awt.Component;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.UIManager;
/**
* Test
* @author Tom
*
*/
public class TestDemo {
public static void main(String[] args) {
try {
String feel = UIManager.getSystemLookAndFeelClassName();
UIManager.setLookAndFeel(feel);
} catch (Exception e) {
e.printStackTrace();
}
JFrame frame = new JFrame();
frame.setTitle("可关闭Tab测试");
frame.setSize(300, 400);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
TabbedPane tabbedPane = new TabbedPane();
tabbedPane.setCloseButtonEnabled(true);
tabbedPane.addTab("测试一", null, new JLabel("测试一"));
tabbedPane.addTab("测试二", null, new JLabel("测试二"));
tabbedPane.addTab("测试三", null, new JLabel("测试三"));
tabbedPane.addTab("测试四", null, new JLabel("测试四"));
tabbedPane.addTabbedPaneListener(new TabbedPaneListener(){
@Override
public void allTabsRemoved() {
// TODO Auto-generated method stub
}
@Override
public boolean canTabClose(Tab tab, Component component) {
// TODO Auto-generated method stub
return false;
}
@Override
public void tabAdded(Tab tab, Component component, int index) {
// TODO Auto-generated method stub
}
@Override
public void tabRemoved(Tab tab, Component component, int index) {
// TODO Auto-generated method stub
System.out.println("close");
}
@Override
public void tabSelected(Tab tab, Component component, int index) {
// TODO Auto-generated method stub
}
});
frame.add(tabbedPane);
frame.setVisible(true);
}
}
测试效果:
源码下载:TabbedPane.rar
发表人: Tom
posted @
2010-10-24 16:44 obpm 阅读(6115) |
评论 (2) |
编辑 收藏
2010年10月10日
在数据库层使用SQL分页可以很大程度增加平台系统程序运行速度与效率。本人只是初入手半数据库半程序的开发,所以对数据库研究不深。于是要收集下列代码以作参考,同时也Post出来可以让需要的人参考一下,高手就请见笑了。说转载说不上,说原创也... 国庆期间在家家里的机子跑DB比较困难,做不了过多测试。不过语句或函数方面本人都仔细看过抄回来的SQL的网页里示例,感觉基本上大同小异,如果有错误查下做相应的修改或百度Google一下应该没什么大问题,也请多多包涵。当然,有机会就会对下列SQL做测试,然后会进行修正。至于每个数据库分页在这就不进行深究,只是列出个可用的方法。
##########
# MySQL#
##########
select * from tlk_buginfo limit startPos, pageSize
startPos: 定义当前页起始位置(不包括startPos)
pageSize: 每页显示数据的条数
##########
# MSSQL#(2005的row_number,暂无2000)
##########
1、
--返回第20-40行数据
select top 20 * from (select row_number() over (order by EmployeeID) as RowNumber, * from HumanResources.Employee) TableNickname where RowNumber>=20
2、
--返回第20-40行数据
select * from (select row_number() over (order by EmployeeID) as RowNumber, * from HumanResources.Employee) TableNickname where RowNumber between 20 and 40
3、
--返回第20-40行数据
with OrderedResults as
(select *, ROW_NUMBER() OVER (order by EmployeeID) as RowNumber FROM HumanResources.Employee)
select * from OrderedResults where RowNumber between 20 and 40
##########
# Oracle#
##########
①采用rownum关键字(三层嵌套)
--返回第5-15行数据
select * from (select row_.*, rownum num from (select * from tlk_buginfo) row_ where rownum<=15) where num>=5
②采用row_number解析函数进行分页(效率更高)
--返回第5-15行数据
select tab.* from (select t.*, row_number() over (order by lastmodified) as num from tlk_buginfo t) tab where num between 5 and 15
##########
# DB2#
##########
select * from (select *, rownumber() over(order by 排序字段 asc ) as rowid from 表名 )as a where a.rowid >= startPage AND a.rowid <endPage
##########
# Hsqldb#
##########
select LIMIT 0 10 表名
收集资料:(allen)
posted @
2010-10-10 21:32 obpm 阅读(383) |
评论 (1) |
编辑 收藏
2010年10月7日
HTML5 是近十年来 Web 标准最巨大的飞跃。和以前的版本不同,HTML 5 并非仅仅用来表示 Web 内容,它的使命是将 Web
带入一个成熟的应用平台,在这个平台上,视频,音频,图象,动画,以及同电脑的交互都被标准化。尽管 HTML 5 的实现还有很长的路要走,但 HTML 5 正在改变
Web。
HTML 最近的一次升级是1999年12月发布的 HTML
4.01。自那以后,发生了很多事。最初的浏览器战争已经结束,Netscape 灰飞烟灭,IE5 作为赢家后来又发展到 IE6, IE7到IE8。Mozilla
Firefox 从 Netscape 的死灰中诞生,并跃居第二位。苹果和 Google 各自推出自己的浏览器,而小家碧玉的 Opera
仍然嘤嘤嗡嗡地活着,并以推动 Web 标准为己命。我们甚至在手机和游戏机上有了真正的 Web 体验,感谢 Opera,iPhone 以及 Google
已经推出的 Android。
然而这一切,仅仅让 Web 标准运动变得更加混乱,HTML 5 和其它标准被束之高阁,结果,HTML 5
一直以来都是以草案的面目示人。
于是,一些公司联合起来,成立了一个叫做 Web Hypertext Application
Technology Working Group (Web 超文本应用技术工作组 - WHATWG) 的组织,他们将重新拣起 HTML 5。这个组织独立于
W3C,成员来自 Mozilla, KHTML/Webkit 项目组,Google,Apple,Opera 以及微软。尽管 HTML 5
草案不会在短期内获得认可,但 HTML 5 总算得以延续。
HTML 5 将带来什么?以下是 HTML 5 草案中最激动人心的部分:
全新的,更合理的 Tag,多媒体对象将不再全部绑定在 object 或 embed Tag
中,而是视频有视频的 Tag,音频有音频的 Tag。本地数据库。这个功能将内嵌一个本地的 SQL 数据库,以加速交互式搜索,缓存以及索引功能。同时,那些离线
Web 程序也将因此获益匪浅。不需要插件的富动画。Canvas 对象将给浏览器带来直接在上面绘制矢量图的能力,这意味着我们可以脱离 Flash 和
Silverlight,直接在浏览器中显示图形或动画。一些最新的浏览器,除了 IE,已经开始支持 Canvas。浏览器中的真正程序。将提供 API
实现浏览器内的编辑,拖放,以及各种图形用户界面的能力。内容修饰 Tag 将被剔除,而使用 CSS。理论上讲,HTML 5 是培育新 Web
标准的土壤,让各种设想在他的组织者之间分享,但 HTML 5 目前仍处于试验阶段。
Mozilla 的技术副总裁 Mike Shaver 说,HTML 5 是一个被寄予厚望的概念,它既是
WHATWG 组织的实验田,又是 W3C 的标准之路。
Shaver 认为,Mozilla 的兴趣和 WHATWG 实验相吻合,Mozilla 在 HTML 5
工作组中非常活跃,我们对一些早期的细则进行实验并将成熟的结果提交 W3C。
在过去的几年,Mozilla 随着各种出现的新标准,推出多个富有前瞻性的项目,包括
Prism,一个用于离线运行 Web 程序的系统,以及 Weave,一个数据存储框架。
Shaver 说,HTML 5 运动肇始于对 W3C 的不耐烦,Web 标准中的很多进展都因 W3C
将重点从 HTML 转移到 XML 而停滞不前。
很多基于 XML 架构的新技术被设计出来替代 HTML,Shaver
说,这不是一条正确的道路,人们不应象黑瞎子掰玉米把样一边掰一边丢。
HTML 5 的新实验在 Firefox 以及 基于 Webkit 的 Safari 和 Chrome
浏览器中逐渐得到强化,但仍有不少问题。
Chrome 的开发者 Darin Fisher 说,Chrome
仍在襁褓中时,就不得不面临几个问题,尽管使用的是最新的 Webkit,HTML 5 的本地数据库功能在 Chrome 的初期版本中并没有实现。因为 Chrome
的沙箱机制和 Webkit 的数据库功能有冲突。
而由于 Chrome 属于秘密开发,Chrome 的开发人员也不便参与 Webkit 的开发。
我们要想保守 Chrome 的秘密,就无法参与 Webkit 社区。Fisher
说,我们很希望可以在某些方面给 Webkit 以帮助,我们拥有众多经验丰富的开发者,我们很想知道人们目前遇到的挑战并乐意提供帮助。
随着 Chrome 的发布,Fisher 说他的团队成员有时会和 Webkit
的人一起吃饭,有些人私下里还成了好朋友。Fisher 称,他们迫切地想同其他 Webkit 开发组一起工作解决离线数据库的问题。
Chrome 里面还包含Google 的开源 Gears 技术,用来实现与 HTML 5 类似的离线功能。
Gears 可以看作已有 API 的替代品,Fisher 说,HTML 5
对新浏览器来说是非常好的东西,但绝大多数用户还使用旧浏览器。Gears 可以让那些旧浏览器也获得这样的 API,我们正在为 HTML 5 版 API 提供兼容。
Gears 兼容性非常好,它正成为将 HTML 5 带向人们桌面的另外一条途径。
目前,绝大多数工作由 Apple,Mozilla, Opera, Google 以及 Trolltech
展开。微软在干什么?IE 因其对 Web 标准的迟钝而闻名,更不要说 HTML 5。但 IE8 可能会做出改变。
微软 IE 平台与 WHAT 工作组主席 Chris Wilson
在邮件中称,我们希望我们现在开始的工作可以在 HTML 工作组创建一套测试系统。Wilson 说,IE 开发组仍然对 HTML 5
的一些提议感到担忧。我觉得工作组的所有成员都会承认我们还有很多事要做。
目前处于 Beta 版的 IE9,已经包含 HTML 5
的诸多新功能。它拥有一个跨文档消息系统,本地存储,以及一些离线事件来检测网络的中断。但还有些功能还未提上议程,如 Canvas。
HTML 5
非常庞大,仍处在开发阶段,我认为浏览器厂商应当尽快达成一致,而每个浏览器的具体实现时间可以自己选择。Web 开发者和浏览器厂商会同意 Wilson
的下面这句话,这确切无疑是一个激动人心的时刻,我们希望看到 Web 成为新的应用平台。
HTML5写的例子(IE9或google浏览器才有效果):
HTML5学习资料:
http://www.chinabyte.com/bang/html5/
收集资料:(denny)
posted @
2010-10-07 21:46 obpm 阅读(2102) |
评论 (1) |
编辑 收藏
2010年9月16日
首先,在jbpm4中,流程定义相关的部署信息就存在
JBPM4_DEPLOYMENT、
JBPM4_DEPLOYPROP及
JBPM4_LOB (存放当发布一个png和xml文件后的流程定义后的记录)。中。
JBPM4_HIST_PROCINST、
JBPM4_HIST_ACTINST两张表中,分别存放的是process Instance、Activity Instance的历史记录,Activity Instance是指流程定义中各个步骤:task descition等存放Process Instance、Activity Instance历史记录的表有了,那他们的当前记录存在什么地方呢?这就需要弄清楚jBPM的另外几个概念。一般而言,在jBPM中,“a process instance is the root of a tree of executions”。因此,当一个流程实例Split出两个并行步骤的时候,在
JBPM4_EXECUTION表中将有三笔相关记录,一笔是代表流程实例的Root Execution,另外两笔是关于上述两个并行步骤的Child Execution。
此外,在jbpm中,Activity的种类是很丰富的,可以是Control Flow Activities,如sub-process,decision等,也可以是Automatic Activity,如java、script、sql等,其中需要人来参与完成的Activity被称为Task,待办任务放在
JBPM4_TASK表中,而历史任务放在
JBPM4_HIST_TASK表中。
对一个Task而言,它可能会有多个Participation(swim lane 同样会有多个Participation),Participation的种类有Candidate、client、owner、Replaced Assignee和viewer,而具体的Participation既可以是单一用户,也可以是用户组,Participation的信息存放在
JBPM4_PARTICIPATION中。
Swim Lane是一种Runtime Process Role,通过Swim Lane,多个Task可以一次分配到同一Actor身上,存放这些信息是表
JBPM4_PARTICIPATION。
JBPM4_ID_GROUP、
JBPM4_ID_MEMBERSHIP、
JBPM4_ID_USER这是基本的权限控制,建议关于用户认证方面还是自己开发一套,这个功能太简单了,难以满足需求。
JBPM4_JOB存放的是Timer的定义。
JBPM4_PROPERTY这是jbpm引擎参数表。
JBPM4_VAR表存放流程临时变量,当流程实例结束后,表中内容清除。
JBPM4_HIST_VAR表存放历史临时变量,但是jbpm4好像还没有对这张表进行利用。
JBPM4_HIST_DETAIL表保存变量变更记录。
了解jbpm4.3以上这18张表后,我们应该在流程运行中,详细观察jbpm是如何对这些表进行操作,以及进行什么样的操作的。
发布一个流程定义后:
JBPM4_DEPLOYMENT新增一条记录
JBPM4_DEPLOYPROP新增三条记录
JBPM4_LOB新增两条记录
开始一个流程startProcessInstanceByKey后:
JBPM4_EXECUTION新增一条记录
JBPM4_TASK新增一条记录
JBPM4_HIST_PROCINST、
JBPM4_HIST_ACTINST分别新增一条记录
JBPM4_HIST_TASK新增一条记录
当执行taskService.setVariables(task.getId(), map);时,
JBPM4_VARIABLES中添加变量记录
转载人员:Nicholas
posted @
2010-09-16 19:51 obpm 阅读(1240) |
评论 (0) |
编辑 收藏
2010年9月14日
权限分析文档
基于RBAC的权限设计模型:
1 RBAC 介绍
RBAC 模型作为目前最为广泛接受的权限模型。
NIST (The National Institute of Standards and Technology,美国国家标准与技术研究院)标准RBAC模型由4个部件模型组成,这4个部件模型分别是基本模型RBAC0(Core RBAC)、角色分级模型RBAC1(Hierarchal RBAC)、角色限制模型RBAC2(Constraint RBAC)和统一模型RBAC3(Combines RBAC)[1]。RBAC0模型如图1所示。
图表 1 RBAC 0 模型
l RBAC0 定义了能构成一个RBAC控制系统的最小的元素集合
在RBAC之中,包含用户users(USERS)、角色roles(ROLES)、目标objects(OBS)、操作operations(OPS)、许可权permissions(PRMS)五个基本数据元素,权限被赋予角色,而不是用户,当一个角色被指定给一个用户时,此用户就拥有了该角色所包含的权限。会话sessions是用户与激活的角色集合之间的映射。RBAC0与传统访问控制的差别在于增加一层间接性带来了灵活性,RBAC1、RBAC2、RBAC3都是先后在RBAC0上的扩展。
l RBAC1 引入角色间的继承关系
角色间的继承关系可分为一般继承关系和受限继承关系。一般继承关系仅要求角色继承关系是一个绝对偏序关系,允许角色间的多继承。而受限继承关系则进一步要求角色继承关系是一个树结构。
l RBAC2 模型中添加了责任分离关系
RBAC2 的约束规定了权限被赋予角色时,或角色被赋予用户时,以及当用户在某一时刻激活一个角色时所应遵循的强制性规则。责任分离包括静态责任分离和动态责任分离。约束与用户-角色-权限关系一起决定了RBAC2模型中用户的访问许可。
l RBAC3 包含了RBAC1和RBAC2
既提供了角色间的继承关系,又提供了责任分离关系。
建立角色定义表。定出当前系统中角色。
因为有继承的问题,所以角色体现出的是一个树形结构。
2 权限设计:
配置资源以及资源的操作 : 这里资源可以定义为一个通用的资源模型。提供通用的资源统一接口。
数据库 ER 图:
关系图:
3 分析:
根据以上的类关系图和ER图可以看出。整个权限可以抽象为五个对象组成。
OrgBean : 用于描述org模型。
Role : 用于描述角色。
Permission : 用于描述权限。
Resource : 用于描述资源。
Operation : 用于描述操作。
其中Permission中有Resource , Operation 的聚合,资源和操作组成权限。
Role 和 Permission 都有自包含。因为设计到权限的继承。
资源Resource 也可能出现一颗树形结构,那资源也要有自包含。
思想 :
权限系统的核心由以下三部分构成: 1. 创造权限, 2. 分配权限, 3. 使用权限,然后,系统各部分的主要参与者对照如下: 1. 创造权限 -Creator 创造, 2. 分配权限 - Administrator 分配, 3. 使用权限 - User :
1. Creator 创造 Privilege , Creator 在设计和实现系统时会划分,一个子系统或称为模块,应该有哪些权限。这里完成的是 Privilege 与Resource 的对象声明,并没有真正将 Privilege 与具体 Resource 实例联系在一起,形成 Operator 。
2. Administrator 指定 Privilege 与 Resource Instance 的关联 。在这一步, 权限真正与资源实例联系到了一起, 产生了 Operator (Privilege Instance )。 Administrator 利用 Operator 这个基本元素,来创造他理想中的权限模型。如,创建角色,创建用户组,给用户组分配用户,将用户组与角色关联等等 ... 这些操作都是由 Administrator 来完成的。
3. User 使用 Administrator 分配给的权限去使用各个子系统。 Administrator 是用户,在他的心目中有一个比较适合他管理和维护的权限模型。于是,程序员只要回答一个问题,就是什么权限可以访问什么资源,也就是前面说的 Operator 。程序员提供 Operator 就意味着给系统穿上了盔甲。 Administrator 就可以按照他的意愿来建立他所希望的权限框架 可以自行增加,删除,管理 Resource 和 Privilege 之间关系。可以自行设定用户 User 和角色 Role 的对应关系。 ( 如果将 Creator 看作是 Basic 的发明者, Administrator 就是 Basic 的使用者,他可以做一些脚本式的编程 ) Operator 是这个系统中最关键的部分,它是一个纽带,一个系在 Programmer , Administrator , User 之间的纽带。
4 权限API
getPermissionByOrgGuid(String orgGuid )
通过传入一个org的Guid , 拿到当前这个org对象都具有那些访问权限。
getSourcePermissionByOrgGuid(String orgGuid , String resouceGuid)
通过传入一个org的Guid 和 一个资源的Guid , 返回改Org对当前这个资源的访问权限。
getPermissionByResourceGuid(String resource)
通过传入一个资源的Guid , 得到当前资源下都有那些权限定义。
havingHeritPermission(String orgGuid , String resouceGuid) : Boolean
传入一个orgGuid, 资源GUID ,查看改OrgGuid下对资源是否有向下继承的权限。这里继承是资源的继承。即对父栏目有权限,可以继承下去对父栏目下的子栏目同样有权限。
havingPermission(String orgGuid , String resourceGuid) : Boolean
判断某Org对某一资源是否用权限。
以上是粗粒度的权限API 。 以下为细粒度的权限:
getOperationByPermission(String permissionGuid)
通过permission 的Guid 得到该permission 的所有有效操作。
getOperationByGuid(String permissionGuid , String resourceGuid)
通过permision的Guid , 资源的Guid 得到该资源下所有的有效操作。
screeningOpreationByGuid (String permissionGuid , String resourceGuid , String orgGuid)
通过permission , resource , org的Guid 得到改Org对这一资源的有效操作。
hasOperation(String operationGuid) : boolean
通过传入的operationGuid 返回是否具有操作权限。
5 权限的实现:
1 .表单式认证,这是常用的,但用户到达一个不被授权访问的资源时, Web 容器就发
出一个 html 页面,要求输入用户名和密码。
2 .用 Filter 防止用户访问一些未被授权的资源, Filter 会截取所有 Request/Response ,
然后放置一个验证通过的标识在用户的 Session 中,然后 Filter 每次依靠这个标识来决定是否放行 Response 。
这个模式分为:
Gatekeeper :采取 Filter 或统一 Servlet 的方式。
Authenticator : 在 Web 中使用 JAAS 自己来实现。
Filter 拦截只是拦截该用户是否有访问这个页面,或这一资源的权限。真正做到显示后拦截是在应用程序内部去做。
做显示拦截提供API , 标签这两种方式
转载人员:Happy
原文地址 http://blog.csdn.net/huanghanzzz2006/archive/2006/12/04/1429666.aspx
posted @
2010-09-14 13:30 obpm 阅读(912) |
评论 (0) |
编辑 收藏
2010年9月3日
flex4帮助文档大小有34M(网页版),上传不了。需要该文档的,请留下你的邮箱地址。
115共享地址:
http://u.115.com/file/f8c22d4e48
flex4api.zip 提取码:f8c22d4e48
原创人员:denny
posted @
2010-09-03 08:50 obpm 阅读(4566) |
评论 (104) |
编辑 收藏
2010年9月1日
图片剪切功能:
效果图:
flex代码:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="init()" xmlns:local="astion.*">
<mx:Script>
<![CDATA[
import mx.controls.Image;
import mx.graphics.ImageSnapshot;
import flash.net.FileReference;
import mx.graphics.codec.JPEGEncoder;
import mx.managers.PopUpManager;
import mx.containers.TitleWindow;
import mx.controls.Alert;
import mx.events.CloseEvent;
import mx.core.IFlexDisplayObject;
import mx.utils.*;
import mx.core.Application;
import astion.Dot;
import astion.ScaleBox;
public static const LINE_WIDTH:Number = 1;//缩放边框宽度
private var file:FileReference;
public var IMAGE_URL:String="http://localhost:8080/cutPicuter/aa/aa.jpg";
private var loader:Loader;
private var bmp:Bitmap;
private var stream:URLStream;
public var realPath:String="D:\myWorkSpace\cutPicuter\WebRoot\aa\aa.jpg";
//初始化数据
private function init():void{
this.loader = new Loader();
this.stream = new URLStream();
this.loader.contentLoaderInfo.addEventListener(Event.COMPLETE,this.onComplete);
this.loader.load(new URLRequest(encodeURI(this.IMAGE_URL)));//解决中文乱码
this.stream.load(new URLRequest(encodeURI(this.IMAGE_URL)));
this.stream.addEventListener(Event.COMPLETE,this.onLoaded);
}
private function onLoaded(e:Event):void
{
var bytearray:ByteArray = new ByteArray();
this.stream.readBytes(bytearray);
if(this.stream.connected)
this.stream.close();
this.loader.loadBytes(bytearray);
}
private function onComplete(e:Event):void
{
try
{
this.bmp = this.loader.content as Bitmap;
var showImage:Image= new Image();
showImage.source=this.loader.content;
canvas.addChild(showImage);
canvas.setChildIndex(box,1);
canvas.setChildIndex(showImage,0);
}
catch(e:Error)
{
}
}
//截图,显示缩放选择框
private function doCapture():void{
box.x = 100;
box.y = 100;
box.visible = true;
}
//获取缩放选择框内的图像
private function getImg():BitmapData{
//截取整个区域
box.scaleEnable = false;
var bmp:BitmapData = ImageSnapshot.captureBitmapData(canvas);
box.scaleEnable = true;
//矩形为要截取区域
var re:Rectangle = new Rectangle(box.x+LINE_WIDTH,box.y+LINE_WIDTH,box.boxWidth-LINE_WIDTH,box.boxHeight-LINE_WIDTH);
var bytearray:ByteArray = new ByteArray();
//截取出所选区域的像素集合
bytearray = bmp.getPixels(re);
var imgBD:BitmapData = new BitmapData(box.boxWidth-LINE_WIDTH,box.boxHeight-LINE_WIDTH);
//当前的bytearray.position为最大长度,要设为从0开始读取
bytearray.position=0;
var fillre:Rectangle = new Rectangle(0,0,box.boxWidth-LINE_WIDTH,box.boxHeight-LINE_WIDTH);
//将截取出的像素集合存在新的bitmapdata里,大小和截取区域一样
imgBD.setPixels(fillre,bytearray);
return imgBD;
}
//预览图片
private function doScan():void{
var t:TitleWindow = new TitleWindow();
t.showCloseButton=true;
t.addEventListener(CloseEvent.CLOSE,closeWindow);
t.width = box.boxWidth+t.getStyle("borderThickness");
t.height =box.boxHeight+t.getStyle("borderThickness")+t.getStyle("headerHeight");
var img:Image = new Image();
img.width = box.boxWidth;
img.height = box.boxHeight;
img.source = new Bitmap(getImg());
t.addChild(img);
PopUpManager.addPopUp(t,this,true);
PopUpManager.centerPopUp(t);
}
private function closeWindow(e:CloseEvent):void{
var t:TitleWindow = e.currentTarget as TitleWindow;
PopUpManager.removePopUp(t);
}
//保存图片到本地
private function downloadPicture():void{
file=new FileReference();
file.addEventListener(Event.COMPLETE,downloadComplete);
file.save(new JPEGEncoder(80).encode(getImg()),"default.jpg");
}
private function downloadComplete(event:Event):void{
Alert.show("成功保存图片到本地!","提示");
}
//保存图片到服务器即覆盖原来的图片
private function save():void{
Alert.show("是否保存剪切图片?","提示",3, this, function(event:CloseEvent):void {
if (event.detail==Alert.YES){
var request:URLRequest = new URLRequest("http://localhost:8080/cutPicuter/servlet/FileManagerSaveFileServlet?realPath="+encodeURIComponent(StringUtil.trim(realPath)));
request.method=URLRequestMethod.POST;
request.contentType = "application/octet-stream";
request.data = new JPEGEncoder(80).encode(getImg());
var loader:URLLoader = new URLLoader();
loader.load(request);
loader.addEventListener(Event.COMPLETE,saveResult);
}});
}
private function saveResult(event:Event):void{
Application.application.reLoadFolderFiles(realPath.substr(0,realPath.lastIndexOf("\\")));
Alert.show("保存剪切图片成功","提示");
}
]]>
</mx:Script>
<mx:HBox x="0" y="0">
<mx:LinkButton label="剪裁" click="doCapture();" icon="@Embed('assets/cut.png')"/>
<mx:LinkButton label="预览" click="doScan();" icon="@Embed('assets/ok.png')"/>
<mx:VRule height="22"/>
<mx:LinkButton label="保存" click="save()" icon="@Embed('assets/save.png')"/>
<mx:LinkButton label="另存为" click="downloadPicture();" icon="@Embed('assets/saveAs.png')"/>
</mx:HBox>
<mx:Canvas id="canvas" y="23" x="1">
<local:ScaleBox id="box" visible="false" y="0" x="0" width="100" height="100"/>
</mx:Canvas>
</mx:Application>
java代码:
package com;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class FileManagerSaveFileServlet
*/
public class FileManagerSaveFileServlet extends HttpServlet {
private int len=0;//处理流
private int mm=0;//重命名
private String fileName="";//文件原名
private String extName="";//文件扩展名
private String tempFileName="";//文件名加扩展名
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
public void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String realPath=request.getParameter("realPath");
//System.out.println("FMSFS-->realPath:"+realPath);
response.setContentType("application/octet-stream");
InputStream is = request.getInputStream();
try {
int size = 0;
byte[] tmp = new byte[100000];
tempFileName=realPath.substring(realPath.lastIndexOf("\\")+1);//切割获得文件名加扩展名
fileName=tempFileName.substring(0,tempFileName.lastIndexOf("."));//切割获得文件名
//确保获得真实的文件名如:1(1)可以获得真实为1,
if(fileName.indexOf("(")!=-1){
fileName=fileName.substring(0,fileName.indexOf("("));
}
extName=tempFileName.substring(tempFileName.lastIndexOf("."));//切割获得扩展名
//调用递归方法
fileName+=reNameFile(realPath.substring(0,realPath.lastIndexOf("\\")+1),fileName,extName);
// 创建一个文件夹用来保存发过来的图片;
File f = new File(realPath.substring(0,realPath.lastIndexOf("\\")+1)+fileName+extName);
DataOutputStream dos = new DataOutputStream(new FileOutputStream(f));
while ((len = is.read(tmp)) != -1) {
dos.write(tmp, 0, len);
size += len;
}
dos.flush();
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//递归来重命名文件名
String str="";
public String reNameFile(String realPath,String filename,String extName){
File file =new File(realPath+"\\"+filename+extName);
str="";
if(file.exists()){
mm++;
str="_"+mm;
reNameFile(realPath,fileName+str,extName);
}else{
if(mm!=0){
str="_"+mm;
}
}
return str;
}
}
源码: flex图片剪切示例
原创人员:Denny
posted @
2010-09-01 09:55 obpm 阅读(8590) |
评论 (6) |
编辑 收藏