??xml version="1.0" encoding="utf-8" standalone="yes"?> 在局域网使用中,我们常常?x)发现系l中开放了一些莫名其妙的端口Q这qpȝ的安全带来了一些隐(zhn)。ؓ(f)了让端口的用尽在掌握之中,一些朋友就?x)用第三方工具来进行检查出使用端口的特定程序究竟是谁,但实际上我们完全不必q样兴师动众Q因为Windows已经内置了这个功能,下面让我们来学习(fn)一下吧Q? 3 Windowsd理?
W一步视觉体验?br />
视觉体验是用户对界面设计的第一感官体验。它是完全是用户几乎没有l过思考前的一U视觉感受,如何l用h供一U近于完的视觉体验Q需要考虑到用L(fng)到界面时可能出现的Q何一U感受,q就提出UI设计师需要对目标用户偏爱的准了解和把握Q精传N要传辄含义Q才?x)获得预期的效果Q视觉体验直接媄响到用户是否停留在此面q行一下步的表辄解。注意:(x)M一U让用户感官视觉不适的界面都可能导致用户生怨言和流失?br />
W二步表达体验?br />
表达体验是用户在视觉体验的基上对界面内容的理解,界面内容可能是文字,也可能是图案Q这些内Ҏ(gu)引导用户q行操作?#8220;提示或说?#8221;Q是需要用戯行理解的内容Q如何给用户提供一U简单直白有易懂的表达体验Q需要品设计h员考虑到用户对需要理解的内容可能出现的Q何一U理解进行预伎ͼ消除一些传辑և错误信息的内容,因ؓ(f)q些内容都是单向的表达,没有解释和补充的Z(x)来纠正用L(fng)间的理解Q表达体验直接媄响到用户下一步的操作行ؓ(f)是否合理。注意:(x)M一U让用户产生误解的表N可能D用户产生怨言和流失?br />
W三步操作体验?br />
操作体验是用户通过对表辑ֆ容的理解后做出的行ؓ(f)动作的体验过E。功能逻辑是操作体验的直接影响因素Q如何优化用L(fng)操作q程是品设计h员需要思考的核心问题之一Q既需要考虑正常的逻辑Q又需要考虑非正常的逻辑形式Q尽可能考虑到用户可能出现的M一U行为方式,才能保证用户q行正确的愉(zhn)的操作q程Q操作体验直接媄响到用户下一步的内容体验。注意:(x)M一U繁琐和复杂的操作逻辑都可能导致用户生怨言和流失?br />
W四步结果体验?br />
l果体验是用户通过操作行ؓ(f)获得的行为结果的一U体验过E。用L(fng)M一U操作可能出现的M一个行为结果都直接影响到用L(fng)果体验。如果通过用户的Q何行为来预估用户的准需求是产品设计人员需要思考的核心问题之一Q这p求涉?qing)好每一U用戯为可能出现的M一U结果,q每一U结果是否能够满用L(fng)需求,如果不能Q如何采用其他方式来满用户的行为需求。注意:(x)M一U不能满用户需求的操作l果都可能导致用户生怨言和流失?br />
ȝQ用hl顶聪明的天才,因ؓ(f)他可能发CQ何一个细微的不Q用hdQ因ZQ何一个微不道的l节p都可能导致用户出现挫败感Q每一个细节看h都微不道,但是每一个细节的l合׃(x)促整个产品于完美Q也许用户只是感动于某个l节Q但他接受你一定是认同你的全部Q?
]]>
用Windows内置功能L查看端口使用情况 [阅读Q?564]
1 查看端口
查看端口开放情?
E有l验的网就?x)知道用Netstat命o(h)可以查看pȝ当前开攄端口有哪些,但你知道吗?如果在用Netstat命o(h)的同时加上参?#8220;-o”的话Q就可以让我们进一步知晓端口的兌q程标识W?(PID)了,也就是说q个PID可用来确定哪个进E(E序Q在使用特定的端口。例如,现在使用“netstat-ano”命o(h)后可以发现端?026?3030?728在开放(如图1所C)?
从上图中q不能直接看三个端口的关联进E是谁,但我们却可以通过PID信息知道?28q个q程在用这三个端口?/p>
Ȁz进EPID
既然知道pȝ中有个PID?28的进E,那么来看看它究竟是谁。大安知道Q查看系l进E可以用同时按“Ctrl+Alt+Delete”l合键的Ҏ(gu)Q在打开?#8220;Windowsd理?#8221;?#8220;q程”选项卡中q行。但默认状态下Q?#8220;q程”选项卡中是没有PIDq一存在的Q这h们就无法知道q程相对应的PID是什么了。因此,要首先激z进E对应的PIDҎ(gu)C状态才行。方法如下:(x)
单击“Windowsd理?#8221;H口?#8220;查看”下的“选择?#8221;菜单,然后单击选中“PID”Q进E标识符Q复选框Q如?所C)?
2 选择q程PID
E后?#8220;Windowsd理?#8221;H口“q程”选项卡的列表中就?x)发现多ZPIDq一,接下来只需按从大到的序查找到PID?28的进E后Q就可以发现“q后E序”I竟是谁了(如图3所C)?/p>
通过上图中显CZ息可以发玎ͼ原来使用端口3026?030?728的关联PID?28Q而用PID?28的应用程序是“MSN Messenger”Q!瞧,我们已经LCؓ(f)端口扑ֈ?#8220;另一?#8221;了!
]]>
q是在一ơ事务提交时遇到的异常?br />
an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
net.sf.hibernate.AssertionFailure: possible nonthreadsafe access to session
注:(x)非possible non-threadsafe access to the session Q那是另外的错误Q类g不一P
q个异常应该很多的朋友都遇到q,原因可能各不相同。但所有的异常都应该是在flush或者事务提交的q程中发生的。这一般由我们在事务开始至事务提交的过E中q行了不正确的操作导_(d)也会(x)在多U程同时操作一个Session时发生,q里我们仅仅讨论单线E的情况Q多U程除了U程同步外基本与此相同?br />
至于具体是什么样的错误操作那Q我l大家看一个例子(假设Hibernate配置正确Qؓ(f)保持代码z,不引入包?qing)处理Q何异常)
SessionFactory sf = new Configuration().configure().buildSessionFactory() ;
Session s = sf.openSession();
Cat cat = new Cat();
Transaction tran = s.beginTransaction(); (1)
s.save(cat); (2)Q此处同样可以ؓ(f)update deleteQ?br />
s.evict(cat); (3)
tran.commit(); (4)
s.close();(5)
q就是引h异常的典型错误。我当时遇Cq个异常Q检查代码时Ҏ(gu)没感觉到q段代码Z问题Q想当然的认为在Session上开始一个事务,通过Session对象存入数据库Q再这个对象从Session上拆,提交事务Q这是一个很正常的流E。如果这里正常的话,那问题一定在别处?br />
问题恰恰在q里Q我的想法也许没有错Q但是一个错误的论据所引出的观Ҏ(gu)q都不可能是正确的。因为我一直以为直接在Ҏ(gu)据库q行操作Q忘C在我与数据库之间隔了一个HibernateQHibernate在ؓ(f)我们提供持久化服务的同时Q也改变了我们对数据库的操作方式Q这U方式与我们直接的数据库操作有着很多的不同,正因为我们对q种方式没有一个大致的了解造成了我们的应用q未得到预先设想的结果?br />
那Hibernate的持久化机制到底有什么不同那Q简单的_(d)Hibernate在数据库层之上实C一个缓存区Q当应用save或者update一个对象时QHibernateq未这个对象实际的写入数据库中Q而仅仅是在缓存中Ҏ(gu)应用的行为做了登讎ͼ在真正需要将~存中的数据flush入数据库时才执行先前登记的所有行为?br />
在实际执行的q程中,每个Session是通过几个映射和集合来l护所有与该Session建立了关联的对象以及(qing)应用对这些对象所q行的操作的Q与我们q次讨论有关的有entityEntriesQ与Session相关联的对象的映)、insertionsQ所有的插入操作集合Q、deletionsQ删除操作集合)、updatesQ更新操作集合)。下面我开始解释在最开始的例子中,Hibernate到底是怎样q作的?br />
(1)生成一个事务的对象Qƈ标记当前的Session处于事务状态(注:(x)此时q未启动数据库事务Q?br />
(2)应用使用s.save保存cat对象Q这个时候Sessioncatq个对象攑օentityEntriesQ用来标记cat已经和当前的?x)话建立了关联,׃应用对cat做了保存的操作,Sessionq要在insertions中登记应用的q个插入行ؓ(f)Q行为包括:(x)对象引用、对象id、Session、持久化处理c)?br />
(3)s.evict(cat)cat对象从s?x)话中拆,q时s?x)从entityEntries中将catq个对象Ud?br />
(4)事务提交Q需要将所有缓存flush入数据库QSession启动一个事务,q按照insert,update,……,delete的顺序提交所有之前登记的操作Q注意:(x)所有insert执行完毕后才?x)执行updateQ这里的Ҏ(gu)处理也可能会(x)你的程序搞得一团糟Q如需要控制操作的执行序Q要善于使用flushQ,现在cat不在entityEntries中,但在执行insert的行为时只需要访问insertionsp够了Q所以此时不?x)有M的异常。异常出现在插入后通知Session该对象已l插入完毕这个步骤上Q这个步骤中需要将entityEntries中cat的existsInDatabase标志|ؓ(f)trueQ由于catq不存在于entityEntries中,此时Hibernatep为insertions和entityEntries可能因ؓ(f)U程安全的问题生了不同步(也不知道Hibernate的开发者是否考虑C子中的处理方式,如果没有的话Q这也许是一个bug吧)Q于是一个net.sf.hibernate.AssertionFailurep抛出Q程序终止?br />
我想现在大家应该明白例子中的E序到底哪里有问题了吧,我们的错误的认ؓ(f)s.save?x)立即的执行Q而将cat对象q早的与Session拆离Q造成了Session的insertions和entityEntries中内容的不同步。所以我们在做此cL作时一定要清楚Hibernate什么时候会(x)数据flush入数据库Q在未flush之前不要已q行操作的对象从Session上拆R?/p>
对于q个错误的解x法是Q我们可以在(2)?3)之间插入一个s.flush()强制Session缓存中的数据flush入数据库Q此时Hibernate?x)提前启动事务,?2)中的save登记的insert语句登记在数据库事务中,q将所有操作集合清I)Q这样在(4)事务提交时insertions集合已l是I的了,即我们拆离了cat也不?x)有M的异怺?br />
前面单的介绍了一下Hibernate的flush机制和对我们E序可能带来的媄响以?qing)相应的解决?gu)QHibernate的缓存机制还?x)在其他的方面给我们的程序带来一些意想不到的影响。看下面的例子:(x)
Qname为cat表的主键Q?br />
Cat cat = new Cat();
cat.setName(“tom”);
s.save(cat);
cat.setName(“mary”);
s.update(cat);(6)
Cat littleCat = new Cat();
littleCat.setName(“tom”);
s.save(littleCat);
s.flush();
q个例子看v来有什么问题?估计不了解Hibernate~存机制的h多半?x)说没有问题Q但它也一样不能按照我们的思\正常q行Q在flushq程中会(x)产生主键冲突Q可能你想问Q?#8220;在save(littleCat)之前不是已经更改cat.nameq已l更C么?Z么还?x)发生主键冲H那Q?#8221;q里的原因就是我在解释第一个例子时所提到的缓存flush序的问题,Hibernate按照insert,update,……,delete的顺序提交所有登记的操作Q所以你的s.update(cat)虽然在程序中出现在s.save(littleCat)之前Q但是在flush的过E中Q所有的save都将在update之前执行Q这造成了主键冲H的发生?br />
q个例子中的更改Ҏ(gu)一h?6)之后加入s.flush()强制Session在保存littleCat之前更新cat的name。这样在W二ơflush时就只会(x)执行s.save(littleCat)q次登记的动作,q样׃?x)出C键冲H的状况?br />
再看一个例子(很奇怪的例子Q但是能够说明问题)
Cat cat = new Cat();
cat.setName(“tom”);
s.save(cat); (7)
s.delete(cat);(8)
cat.id=null;(9)
s.save(cat);(10)
s.flush();
q个例子在运行时?x)生异常net.sf.hibernate.HibernateException: identifier of an instance of Cat altered from 8b818e920a86f038010a86f03a9d0001 to null
q里例子也是有关于缓存的问题Q但是原因稍有不同:(x)
Q?Q和Q?Q的处理相同?br />
Q?QSession?x)在deletions中登记这个删除动作,同时更新entityEntries中该对象的登记状态ؓ(f)DELETED?br />
Q?QCatcȝ标识W字Dؓ(f)id,其|ؓ(f)null便于重新分配idq保存进数据库?br />
Q?0Q此时Session?x)首先在entityEntries查找cat对象是否曄与Session做过兌Q因为cat只改变了属性|引用q未改变Q所以会(x)取得状态ؓ(f)DELETED的那个登记对象。由于第二次保存的对象已l在当前Session中删除,save?x)强制Session缓存flush才会(x)l箋Qflush的过E中首先要执行最开始的save动作Q在q个save中检查了catq个对象的id是否与原来执行动作时的id相同。不q的是,此时cat的id被赋为nullQ异常被抛出Q程序终止(此处要注意,我们在以后的开发过E尽量不要在flush之前改变已经q行了操作的对象的idQ?br />
q个例子中的错误也是׃~存的g时更新造成的(当然Q与不正规的使用Hibernate也有关系Q,处理Ҏ(gu)有两U:(x)
1、在Q?Q之后flushQ这样就可以保证Q?0Q处savecat作ؓ(f)一个全新的对象q行保存?br />
2、删除(9Q,q样W二ơsave所引v的强制flush可以正常的执行,在数据库中插入cat对象后将其删除,然后l箋W二ơsave重新插入cat对象Q此时cat的id仍与从前一致?br />
q两U方法可以根据不同的需要来使用Q呵呵,总觉得好像是很不正规的方式来解决问题Q但是问题本w也不够正规Q只希望能够在应用开发中l大家一些帮助,不对的地方也希望各位l与指正?br />
ȝ来说Q由于Hibernate的flush处理机制Q我们在一些复杂的对象更新和保存的q程中就要考虑数据库操作顺序的改变以及(qing)延时flush是否对程序的l果有媄响。如果确实存在着影响Q那可以在需要保持这U操作顺序的位置加入flush强制Hibernate缓存中记录的操作flush入数据库Q这L(fng)h也许不太观Q但很有效?/p>
分三U情况:(x) 单类型排序?/p> 内部对象实现comparable?/p> 外部对象实现comparator?/p> 1、简单类型的排序 单类型不外是byte, char, short, int, long, float, double{数据类型,q些cd不能攑֜聚集中,只能使用数组?font face="Times New Roman">java.util.ArraysҎ(gu)提供了对q些cd?font face="Times New Roman">sortҎ(gu)Q实际上q有很多其他有用的方法)Q下面是对一个简单的int数组排序Q?/p> int[] arr = {2, 3, 1,10,7,4}; System.out.print("before sort: "); for (int i = 0; i< arr.length; i++) System.out.print(arr[i] + " "); System.out.println(); Arrays.sort(arr); System.out.print("after sort: "); for (int i = 0; i< arr.length; i++) System.out.print(arr[i] + " "); System.out.println(); 输出l果Q?/p> before sort: 2 3 1 10 7 4 after sort: 1 2 3 4 7 10 我们看到排序l果是按照升序排列的Q下面的排序都是如此?/p> Comparable & Comparator 都是用来实现集合中的排序的,只是Comparable是在集合内部定义的方法实现的排序Q?font face="Times New Roman">Comparator是在集合外部实现的排序,所以,如想实现排序Q就需要在集合外定?font face="Times New Roman">Comparator接口的方法或在集合内实现Comparable接口的方法?/strong> 2、内部对象实?font face="Times New Roman">comparable?/p> 案例Q?/p> class Programmer implements Comparable{ private String name; private String language; private double pay;
public Programmer(String name, String language, double pay) { this.name = name; this.language = language; this.pay = pay; } public int compareTo(Object o) { Programmer other = (Programmer)o; return (int)pay - (int)other.pay; } public String toString(){ return "{name: " + name + ", language: " + language + ", money: " + pay + "}"; } } 对其q行排序Q?/p> ArrayList list = new ArrayList(); list.add(new Programmer("张三", "C", 12000)); list.add(new Programmer("李四", "Java", 200)); list.add(new Programmer("王五", "C++", 5000)); list.add(new Programmer("钱六", "VB", 3000)); System.out.println("before sort: " + list); Collections.sort(list); System.out.println("after sort: " + list); 3、外部对象实?font face="Times New Roman">comparator?/p> 案例Q?/p> import java.util.Arrays; |