Java开发者需坚守的十条基本原则

有许多标准和实践准则可适用于Java开发者,但此处要说的,是每个Java开发者需坚守的基本原则。

一、为代码加注释。虽然每个人都知道这点,但有时却不自觉忘了履行,今天你“忘了”加注释了吗?虽然注释对程序的功能没什么“贡献”,但过一段时间,比如说两星期之后或者更长,回过头来看看自己的代码,说不定已经记不住它是干什么的了。如果这些代码是你个人的,那还算是走运了,不幸的是,当然了,大多数时候都是别人的不幸,很多时候大家都是在为公司写代码,写代码的人也许早已经离开了公司,但别忘了一句古话,有来有往嘛,为他人,也为我们自己,请为你的代码加上注释。

二、不要让事情复杂化。程序员有时候总是对简单问题想出复杂的解决方案,比如说,在只有五个用户的程序中引入EJB、对程序实现了并不需要的框架(framework),之类的还有属性文件、面向对象解决方案、多线程等等。为什么要这样做呢?也许我们并不知道是否这样会更好,但这样做也许可以学到一些新东西,或者让自己更感兴趣一些。如果是不知道为什么这样做,建议多请教经验丰富的程序员,如果是为了个人的目的,麻烦让自己更专业一点。
三、始终牢记——“少即是好(Less?ismore)并不总是对的代码效率虽然很重要,但在许多解决方案中,编写更少的代码并不能改善这些代码的效率,请看下面这个简单的例子:

if(newStatusCode.equals(“SD”)?&&(sellOffDate?==?null?||
todayDate.compareTo(sellOffDate)<0?||?(lastUsedDate?!=?null?&&
todayDate.compareTo(lastUsedDate)>0))?||
(newStatusCode.equals(“OBS”)&&?(OBSDate?==?null?||
todayDate.compareTo(OBSDate)<0))){
newStatusCode?=?”NYP”;
}
能看明白if条件语句是干什么的吗?能想出来是谁写的这段代码吗?如果把它分成两段独立的if语句,是不是更容易理解呢,下面是修改后的代码:

if(newStatusCode.equals(“SD”)?&&(sellOffDate?==?null?||
todayDate.compareTo(sellOffDate)<0?||?(lastUsedDate?!=?null?&&
todayDate.compareTo(lastUsedDate)>0))){
newStatusCode?=?”NYP”;
}elseif(newStatusCode.equals(“OBS”)?&&(OBSDate?==?null?||
todayDate.compareTo(OBSDate)<0))
{
newStatusCode?=?”NYP”;
}
是不是读起来容易多了呢,在此只是多加了一个if和两个花括号,但代码的可读性与可理解性就一下子提高了一大截。

四、请不要硬编码。开发者经常有意“忘记”或忽略掉这点,因为有些时候开发日程逼得实在太紧。其实,多写一行定义静态变量的代码能花多少时间呢?

public?class?A?{
public?static?final?String?S_CONSTANT_ABC?=?”ABC”;
public?boolean?methodA(String?sParam1){
if?(A.S_CONSTANT_ABC.equalsIgnoreCase(sParam1)){
return?true;
}
return?false;
}
}

现在,每次需要将“ABC”与其他变量进行比较时,不必记住实际代码,直接引用A.S_CONSTANT_ABC就行了,而且在今后需要进行修改时,也可在一处修改,不会翻遍整个源代码逐个修改了。

五、不要“创造”自己的框架(framework)。确切来说,有数以千计的各种框架存在,而且大多数是开源的,这些框架都是优秀的解决方案,可用于日常程序开发中,我们只需使用这些框架的最新版本就行了,至少表面上要跟上形势吧。被大家广为接受的最为明显的一个例子就是Struts了,这个开源web框架非常适合用在基于web的应用程序中。是不是想开发出自己的Struts呢,还是省点力气吧,回头看看第二条——不要让事情复杂化。另外,如果正在开发的程序只有3个窗口,就不要使用Struts了,对这种程序来说,不需要那么多的“控制”。

六、不要使用println及字符串连接。通常为了调试方便,开发者喜欢在可能的所有地方都加上System.out.println,也许还会提醒自己回过头来再来删除,但有些时候,经常会忘了删除或者不愿意删除它们。既然使用System.out.println是为了测试,那么测试完之后,为什么还要留着它们呢,因为在删除时,很可能会删除掉真正有用的代码,所以不能低估System.out.println危害啊,请看下面的代码:

public?class?BadCode?{
public?static?void?calculationWithPrint(){
double?someValue?=?0D;
for?(int?i?=?0;?i?<10000;?i++)?{
System.out.println(someValue?=?someValue?+i);
}
}
public?static?void?calculationWithOutPrint(){
double?someValue?=?0D;
for?(int?i?=?0;?i?<?10000;?i++)?{
someValue?=?someValue?+?i;
}
}
public?static?void?main(String?[]?n)?{
BadCode.calculationWithPrint();
BadCode.calculationWithOutPrint();
}
}

从测试中可以发现,方法calculationWithOutPrint()执行用了0.001204秒,作为对比,方法calculationWithPrint()执行可是用了10.52秒。

要避免浪费CPU时间,最好的方法是引入像如下的包装方法:

public?class?BadCode?{
public?static?final?int?DEBUG_MODE?=?1;
public?static?final?int?PRODUCTION_MODE?=?2;
public?static?void?calculationWithPrint(int?logMode){
double?someValue?=?0D;
for?(int?i?=?0;?i?<?10000;?i++)?{
someValue?=?someValue?+?i;
myPrintMethod(logMode,?someValue);
}
}
public?static?void?myPrintMethod(int?logMode,?double?value)?{
if?(logMode?>?BadCode.DEBUG_MODE)?{?return;?}
System.out.println(value);
}
public?static?void?main(String?[]?n)?{
BadCode.calculationWithPrint(BadCode.PRODUCTION_MODE);
}
}

另外,字符串连接也是浪费CPU时间的一个大头,请看下面的示例代码:

public?static?void?concatenateStrings(StringstartingString)?{
for?(int?i?=?0;?i?<?20;?i++)?{
startingString?=?startingString?+startingString;
}
}
public?static?voidconcatenateStringsUsingStringBuffer(String?startingString)?{
StringBuffer?sb?=?new?StringBuffer();
sb.append(startingString);
for?(int?i?=?0;?i?<?20;?i++)?{
sb.append(sb.toString());
}
}

在测试中可发现,使用StringBuffer的方法只用了0.01秒执行完毕,而使用连接的方法则用了0.08秒,选择显而易见了。

七、多关注GUI(用户界面)。再三强调,GUI对商业客户来说,与程序的功能及效率同等重要,GUI是一个成功程序的最基本部分,而很多IT经理往往都没注意到GUI的重要性。在现实生活中,许多公司可能为了节省开支,没有雇用那些有着设计“用户友好”界面丰富经验的网页设计者,此时Java开发者只能依赖他们自身的HTML基本功及在此领域有限的知识,结果,很多开发出来的程序都是“计算机友好”甚于“用户友好”。很少有开发者同时精通软件开发及GUI设计,如果你在公司“不幸”被分配负责程序界面,就应该遵守下面三条原则:

1?不要再发明一次轮子,即不做无用功。现有的程序可能会有类似的界面需求。
2?先创建一个原型。这是非常重要一步,用户一般想看到他们将使用的东西,而且可以先利用这个原型征求用户的意见,再慢慢修改成用户想要的样子。
3?学会换位思考。换句话来说,就是从用户的角度来审查程序的需求。举例来讲,一个汇总的窗口可以跨页或者不跨页,作为一个软件开发者,可能会倾向于不跨页,因为这样简单一些。但是,从用户的角度来看,可能不希望看到上百行数据都挤在同一页上。

八、文档需求不放松。每个商业需求都必须记录在案,这可能听上去像童话,似乎在现实生活中很难实现。而我们要做的是,不管开发时间多紧迫,不管最终期限多临近,对每个商业需求都必须记录在案。

九、单元测试、单元测试、单元测试。关于什么是单元测试的最好方法,在此不便细说,只是强调,单元测试一定要完成,这也是编程中最基本的原则。当然了,如果有人帮你做单元测试自然是最好,如果没有,就自己来做吧,当创建一个单元测试计划时,请遵守以下三条最基本的原则:

1?先于编写类代码之前编写单元测试。
2?记录单元测试中的代码注释。
3?测试所有执行关键功能的公有方法,这里不是指setget方法,除非它们是以自己独特方式执行setget方法。?

十、质量,而不是数量。有些时候因为产品问题、期限紧迫、或一些预料之外的事情,导致常常不能按时下班,但一般而言,公司不会因为雇员经常加班而对之表扬和奖励,公司只看重高质量的工作。如果遵守了前九条原则,你会发现自己写出的代码bug少且可维护性高,无形中质量提高了一大步。

 

jQuery扩展类库thickbox实现弹出层

1>?引用JQuery插件、thickbox插件;

<script?type="text/javascript"?src="path-to-file/jquery.js"></script>?
<script?type="text/javascript"?src="path-to-file/thickbox.js"></script>

2>?引入thickbox的css文件;

<link?rel="stylesheet"?href="path-to-file/thickbox.css"?type="text/css"?media="screen"?/>

3>?对需要使用?thickbox效果的对象加入以下代码, 给创建的这个link元素一个class="thickbox"属性;

 <a?href="Upimg/single.jpg"?title="add?a?caption?to?title?attribute?"?class="thickbox">
??????对象/图片
?</a>

一、一张图片

<1>给创建的这个link元素一个??class="thickbox"??属性
调用代码如下:

<a?href=”Upimg/single.jpg”?title=”add?a?caption?to?title?attribute?”?class=”thickbox”>

 

 

 

<img?src=”Upimg/single_t.jpg”?alt=”Image?2″/>
</a>

二、多张图片

 <1>给创建的这个link元素一个??class="thickbox"??属性
<2>给每一个link元素一个相同的rel值。(比如:rel="gallery-plants")


<a?href="Upimg/plant1.jpg"?title="add?a?caption?"?class="thickbox"?rel="gallery-plants">
?<img?src="Upimg/plant1_t.jpg"?alt="Plant?1"?/>
</a>?

<a?href="Upimg/plant2.jpg"?title="add?a?caption"?class="thickbox"?rel="gallery-plants">
??????<img?src="Upimg/plant2_t.jpg"?alt="Plant?2"?/>
</a>?

<a?href="Upimg/plant3.jpg"?title="add?a"?class="thickbox"?rel="gallery-plants">
??????<img?src="Upimg/plant3_t.jpg"?alt="Plant?3"?/>
</a>?

三、?层

 <1>给创建的这个link元素一个??class="thickbox"??属性
<2>给link元素的href属性设置为:?#TB_inline
<3>在href属性的值#TB_inlineIn后面追加一下字符:??height=300&width=300&inlineId=myOnPageContent
????当然你也可以在参数字符串中加?modal=true(比如.?#TB_inline?height=155&width=300&inlineId=hiddenModalContent&modal=true)?这样当关闭ThickBox时会调用ThickBox内部的一个tb_remove()函数。在演示中查看“显示隐藏模式的内容”则要求点击yes?或?no才能关闭ThickBox。

??代码如下:

<input?alt="#TB_inline?height=300&width=400&inlineId=myOnPageContent"?title="add?a?caption"?class="thickbox"?type="button"?value="Show"?/>?

<div?id="myOnPageContent">
?<p>Lorem?ipsum?dolor?sit?amet,?consectetuer?adipiscing?elit,?sed?diam?nonummy?nibh?euismod?tincidunt?ut?laoreet?dolore?magna?aliquam?erat?volutpat.?Ut?wisi?enim?ad?minim?veniam,?quis?nostrud?exerci?tation?ullamcorper?suscipit?lobortis?nisl?ut?aliquip?ex?ea?commodo?consequat.</p>
?<p><select?name=""><option>测试</option></select></p>
</div>

四、iframe

<1>给创建的这个link元素一个??class="thickbox"??属性?
<2>?
href属性的URL后面追加上以下字符参数:??KeepThis=true&TB_iframe=true&height=400&width=600
代码如下:

<a?href="Upimg/ajax_ifram.html?keepThis=true&TB_iframe=true&height=250&width=400"?title="add?a?caption?to?title?attribute?/?or?leave?blank"?class="thickbox">
????例子1
</a>?

参考:http://blog.sina.com.cn/s/blog_64d8a1d00100i7r5.html

获取对象在浏览器中的坐标(转)

一、定义

getBoundingClientRect?函数是W3C组织在第一版本的W3C?CSSOM?View?specification草案中确定的一个标准方法,在此之前,只有IE浏览器是支持该方法的,W3C在这次草案中把它扶正成为标准,足可以看出它并不简单。getBoundingClientRect?方法返回的是调用该方法的元素的TextRectangle对象,该对象具有top、left、right、bottom四个属性,分别代表该元素上、左、右、下四条边界相对于浏览器窗口左上角(注意,不是文档区域的左上角)的偏移像素值。

二、兼容性

getBoundingClientRect方法最先在IE5中出现,后来被W3C接纳成为标准。目前IE5.5+、Firefox?3.5+、Chrome?4+、Safari?4.0+、Opara?10.10+等浏览器均支持该方法,兼容性几乎完美。

在具体表现方面,Firefox6以前的版本使用getBoundingClientRect时不能获取到top和bottom这两个属性值,Firefox6及以后的版本和其他支持getBoundingClientRect方法的浏览器则top、left、right、bottom四个属性值均能获取到。需要说明的是由于某些版本的IE浏览器的<html>文档根元素默认是有2px边框的,所以这里需要特别处理一下,微软MSDN上说在IE5中会存在这样的情况,但据我实际测试,xp系统中IE6也存在这样的问题,奇怪的是,我在win7环境下用IETester测试的IE各版本都是正常的。但这并不是什么大问题,我们只要把得到的值减去html根元素(body也可考虑进来)的clientLeft或clientTop就能保持各浏览器一致啦。

三、用途

当getBoundingClientRect刚被w3c列为标准的时候,PPK还曾质疑过它是不是多此一举,因为已经存在类似的方法来获取元素的偏移位置,比如offsetLeft和offsetTop。但Jquery的作者John?Resig马上阐明了getBoundingClientRect的用处。用传统的方法固然可以实现getBoundingClientRect同样的功能,但兼容各种浏览器以及各种不同的元素就会把你弄死,而且效率还非常低下。所以获取页面上某个元素相对于浏览器窗口的偏移量就成了getBoundingClientRect的用武之地了。而获取元素的偏移量能有什么用,我相信,你懂的~?^_^

 

IE6和IE8区别(待整理)

IE6是单线程(解析标签会等待有阻塞,例如object没指定src属性),IE8是双线程。

IE8与IE6和IE7的区别(转载整理):

1?IE8中的css中关于width或是height中如果使用像素形式作为参数时,参数必须是带“px”的,而且此参数必须是大于0的,而在IE6和IE7中是支持不带“px”参数的,而且参数是可以为一个负数。
2?IE8中的css中“border-style:outset?;”是没有效果的。
3?IE8中的无序列表<ui>之间的距离要比IE6和IE7大的多,而且我还没有找到调整的方法。
4?在IE8中,一个Iframe中取event.x的值不是Iframe中的相对x坐标,而是最外层的window的x坐标,但是event.y却是取的是?Iframe中的相对y坐标。而在IE6和IE7中,event.x和event.y却得的都是所在Iframe中的相对坐标,真是搞不懂!可以用?event.clinetX代替。
5?IE8中的javascript中function对象例如:
??????function?a(){
????????????alert(”haha”);
???????}
??????var?fun=new?Function(“”,a);
??????alert(fun);
此时返回的值为function?anonymous(){function?a(){alert(“haha”)}}?而在IE6和IE7中返回的值为function?anonymous(){alert(“haha”)};也就是说当Function的第二个参数如果是一个函数时,IE8对此参数作用的是整个函数的代码,而IE6和IE7则是对此参数起作用的是函数的内部代码(不包括?“function?a(){”和“}”的函数头和尾)
6?IE8中expression函数不起作用。所以如何在css中写javascript代码还不清楚。
7.如下代码
.regDiv{
????background-image:url(image/bg.gif);?MARGIN:?0px?auto;?WIDTH:?800px;
}
.regWrap{
????vertical-align:center?;border:0px?;margin:0?auto;?width:95%
}
.regWrap?TD{
????FONT:?12px/25px?’arial’;
????VERTICAL-ALIGN:?buttom;
????PADDING-TOP:?2px;
????PADDING-BOTTOM:?2px;
????PADDING-LEFT:5px;
????white-space:nowrap;
????vertical-align:bottom;
}
.regWrap?EM?{
????PADDING-RIGHT:?5px;?PADDING-LEFT:?0px;?PADDING-BOTTOM:?0px;?COLOR:?#cc0000;?PADDING-TOP:?0px
}
.regWrap?SPAN{
????PADDING-RIGHT:?0px;?PADDING-LEFT:?0px;?PADDING-BOTTOM:?0px;?PADDING-TOP:?0px;OVERFLOW:?hidden;?HEIGHT:?20px;color:?#999999
}
.regWrap?INPUT{
????HEIGHT:?18px
}
A{
????FONT:?12px/12px?’arial’;
????COLOR:?#039;
????TEXT-DECORATION:?none;
}
这段代码中如果在IE8以下版本中,A的样式是无效的,而在IE8中是有效的。但是如果把A{……}的样式放在.regWrap{……}前面,这样IE8及以下版本中A的样式就都有效了。
@看了下。。?。在IE6里面做的网站其中的高度为一像素表格在IE8里面显示的不是一像素了。?总之变的很明显的大了
@bug?or?something?else
<div?style=”width:300px;float:left;clear:both;(这里的clear无关紧要似的)”>
<a?href=”#”><img?alt=””?src=”tl.png”/></a><a?href=”#”><img?alt=””?src=”pl.png”/></a>
</div>
以上这段代码,在IE8里面,如果我们给img一个float:left;属性那么a标签就会自动产生3px的margin-left(也可以理解为?img标签会吧),即便在样式里面用a{padding:0;margin:0;}都不行,给img这样做也不行,即便是inline?style;再者,如果我们给a一个width属性,那么除了3px的margin-left,我们还能看到4像素的margin-top或者说是?padding-top在掉下来的第二个a标签的头部,但是在IE8以前版本以及其他浏览器上是正常显示的(虽然给imgfloat属性是没有必要的)。。。
解决方案?暂时没有吧——但是可以避免,就是不要滥用float;
困惑
<div?class=”layout-right”>
<div?class=”list-1?height-72″?style=”width:?100%;float:left;”><a?href=”mailto:hanwei@mail.hust.edu.cn”><img?alt=”团长信箱”?src=”images/tl.png”?/></a><a?href=”mailto:zb2004@mail.hust.edu.cn”><img?alt=”书记信箱”?src=”images/pl.png”?/></a></div>
<div?class=”list-2″?style=”width:?273px;float:left;”>
。。。
这个地方有点纠结——因为两张图片的宽度加起来正好一共300px,而整个容器也是layout-right,list-1,list-2都是?300px,内第一个div,给浮动,里面的图片似乎也得给浮动(这和第一个例子不一样,似乎是因为外面的大容器对内部的内部的元素也产生了影响),不然会自动选择换行显示,且头部还会多出一点间距来(已经给img,a?padding,margin在外导入样式表清0了)即便理论上是刚刚能挤下来(这是在除IE8的nav里都能做到的),好,那我们给img浮动吧,可是很不幸,第二个a标签会向下掉若干个像素(具体什么规律和原理我还不知道),虽然a?img?的margin?padding清0工作是已经做了的——
但是如果给a,img一个inline?style?margin?padding?0?,又偏偏能起到作用,这让我怀疑自己代码的规范性了——但我确实给了a,img一个margin?padding清零的class,而且并未被覆盖。

 

javascript中window与document(转载整理)

window对象和document对象的区别

一般来讲,一个window里就是一个document,但是,iframe里面也可以装个document,在iframe里面就有区别了

alert(document.location?===?window.location);?//?true

不要混淆Window对象的location属性和Document对象的location属性。

前者引用一个Location对象,而后者只是一个只
读字符串,并不具有Location对象的任何特性。

document.location与document.URL是同义的,后者在
JavaScript1.1中是该属性的首选名称(因为这样避免了潜在的混淆)。

在大多数情况下,document.location和
location.href是相同的。但是,当存在服务器重定向时,

document.location包含的是已经装载的URL,而
location.href包含的则是原始请求的文档的URL。
document.location和window.location有什么区别就是
document你可以理解为文档,就是你的网页
window理解为窗口,就是你的ie浏览器包含的
无框架:简单的说,没有框架的情况下,是等同的
有框架:在有框架的情况下,最外层是相同的,

在iframe里面的document.location和window.location不同的。
iframe里面的document.location?你看不ie地址变化,只改变iframe部分,
此时的window.location和top.location效果一致
document.location=”url”;(只读)

document.location.reload(“url”;);
window.location=”url”;
location=”url”;
document.href=”url”;
document.location.href=”url”;
document.location.replace=”url”;
document.action=”url”;

document.submit();
document.location.href;和document.location.replace;

都可以实现从A页面切换到B页面,但他们的区别是:
用document.location.href切换后,可以退回到原页面。

而用document.location.replace切换后,不可以通过“后退”退回到原页面。
关于document.location.href或其他可回退的切换方式
document.location?相当于?document.URL?声明了装载文档的URL,
除非发生了服务器重定向,?否则该属性的值与Window.location.href的值是一样的.
history.go(-1);//返回上一页
document.IFRAME名称.location.href=’url’;//改变框架内容

 

Javascript浮点数比较大小

今天在修改bug的时候发现个关于2个浮点数之和和第3?数比较大小的问题,2个数之和通过人工计算的确和第3个数相等,但是js在判断的时候就变成不相等了,最后发现是2个浮点数相加后出现了精度缺失,正确的比较方式应该如下所示:

return?Math.abs((1*num3)?-?((1*num1)?+?(1*num2)))?<?0.01?true:false;

利用差值的绝对值的精度来判断:

具体就是:f1和f2是两个浮点数,precision是我们自己设置的精度,比如1e-6。

则可以用?fabs(f1-f2)<=precision?来判断f1和f2是否相等。

如果要求更高的精度,则把precision定得更小就行了。

 

UML的9种图及4+1视图简介(整理)

UML中包括九种图:?用例图、类图、对象图、状态图、时序图、协作图、活动图、组件图、配置图
1)用例图(Use?Case?Diagram)
它是UML中最简单也是最复杂的一种图。说它简单是因为它采用了面向对象的思想,又是基于用户视角的,绘制非常容易,简单的图形表示让人一看就懂。说它复杂是因为用例图往往不容易控制,要么过于复杂,要么过于简单。
用例图表示了角色和用例以及它们之间的关系。
2)类图(Class?Diagram)
???????是最常用的一种图,类图可以帮助我们更直观的了解一个系统的体系结构。通过关系和类表示的类图,可以图形化的方式描述一个系统的设计部分。
3)对象图(Object?Diagram)
对象图是类图的实例,几乎使用与类图完全相同的标识。它们的不同点在于对象图显示类的多个对象实例,而不是实例的类。一个对象图是类图的一个实例。由于对象存在生命周期,因此对象图只能在系统某一时间段存在。
4)状态图
描述一个实体基于事件反应的动态行为,显示了该实体如何根据当前所处的状态对不同的时间做出反应的。通常创建一个UML状态图是为了以下的研究目的:研究类、角色、子系统、或组件的复杂行为。
5)时序图
又称顺序图,描述了对象之间动态的交互关系,着重体现对象间消息传递的时间顺序。
顺序图由一组对象构成,每个对象分别带有一条竖线,称作对象的生命线,它代表时间轴,时间沿竖线向下延伸。顺序图描述了这些对象随着时间的推移相互之间交换消息的过程。消息用从一务垂直的对象生命线指向另一个对象的生命线的水平箭头表示。图中还可以根据需要增加有关时间的说明和其他注释。
6)协作图
协作图用于显示组件及其交互关系的空间组织结构,它并不侧重于交互的顺序。协作图显示了交互中各个对象之间的组织交互关系以及对象彼此之间的链接。与序列图不同,协作图显示的是对象之间的关系。另一方面,协作图没有将时间作为一个单独的维度,因此序列号就决定了消息及并发线程的顺序。协作图是一个介于符号图和序列图之间的交叉产物,它用带有编号的箭头来描述特定的方案,以显示在整个方案过程中消息的移动情况。
协作图用途:
通过描绘对象之间消息的移动情况来反映具体的方案。
显示对象及其交互关系的空间组织结构,而非交互的顺序。
7)活动图(Activity?Diagram)
UML活动图记录了单个操作或方法的逻辑,单个用户案例,或者单个业务流程的逻辑。描述系统中各种活动的执行顺序,通常用于描述一个操作中所要进行的各项活动的执行流程。同时,它也常被用来描述一个用例的处理流程,或者某种交互流程。
活动图由一些活动组成,图中同时包括了对这些活动的说明。当一个活动执行完毕之后,控制将沿着控制转移箭头转向下一个活动。活动图中还可以方便地描述控制转移的条件以及并行执行等要求。
8)组件图(Component?Diagram)
组件图是用来反映代码的物理结构。从组件图中,可以了解各软件组件(如源代码文件或动态链接库)之间的编译器和运行时依赖关系。使用组件图可以将系统划分为内聚组件并显示代码自身的结构。
组件图的主要目的是显示系统组件间的结构关系。
9)配置图
配置图描述系统中硬件和软件的物理配置情况和系统体系结构。
在配置图中,用结点表示实际的物理设备,如计算机和各种外部设备等,并根据它们之间的连接关系,将相应的结点连接起来,并说明其连接方式。在结点里面,说明分配给该结点上运行的可执行构件或对象,从而说明哪些软件单元被分配在哪些结点上运行

4+1视图模型概况??

Kruchten?提出了一个”4+1″视图模型,从5个不同的视角包括包括逻辑试图、进程视图、物理视图、开发视图、场景视图来描述软件体系结构。每一个视图只关心系统的一个侧面,5个试图结合在一起才能反映系统的软件体系结构的全部内容。如下图:

通常我们选择UML来表现各种视图,以下列出了UML和各视图的对应关系
4+1视图???????????????????????????????????UML
场景视图????????????????????????????use?case
逻辑视图????????????????????????????类图
开发视图????????????????????????????类图,组件图
进程视图????????????????????????????无完全对应
部署视图????????????????????????????部署图
在架构设计稳定中通常不会给出较多的用例描述,这些是在需求稳定中定义。但是往往架构文档会选择一些用例,列入文档中,这些用例和一些非功能性需求一起用以证明架构的有效和正确性。在逻辑视图中用例的实现是必不可少的一节,尽管架构设计更关注非功能性需求。

 

修改WAMP默认端口

?前几日自己搭建WAMP的环境,在搭建的过程中发现WAMP使用的端口和以前安装的tomcat,apache等软件使用的端口冲突了,在网上查找了一番终于找到了修改的方式。

安装文件下载地址:http://www.wampserver.com/en/?

一、修改APACHE的监听端口,

1、在界面中选apache,弹出隐藏菜单选项,打开配置文件httpd.conf;

2、找到Listen?80?和?ServerName?localhost:80;

3、将80改成801(当然自己也可以设定别的不使用的端口,例如8000等);

4、保存,待重启WAMP服务后即可。

二、修改WAMP打开默认页?Localhost和phpMyadmin的端口:

1、打开wamp目录下wampmanager.tpl文件

2、找到

Parameters:?”http://localhost/”;?Glyph:?5

Parameters:?”http://localhost/phpmyadmin/”;?Glyph:?5

3、改成

Parameters:?http://localhost:801/;?Glyph:?5

Parameters:?”http://localhost:801/phpmyadmin/”;?Glyph:?5

4、保存,重启wamp所有服务即可。

phpmyadmin使用wamp5启动提示密码错误,一般发生在曾经配置过php+apache的机器上,如果记得密码,可以通过以下的方式修改wamp5中phpmyadmin的默认设置,使服务正常。

修改phpmyadmin的默认密码:

1、进入安装盘符下wampapps下的phpmyadmin文件夹

2、打开config.inc文件

3、找到

$cfg[‘Servers’][$i][‘user’]?=?’root’;

$cfg[‘Servers’][$i][‘password’]?=?’这里填写你的密码’;

4、修改好你的密码,保存即可。

 

将javabean转换成xml

使用到的第三方包:org.apache.commons.betwixt

代码片段如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import org.apache.commons.betwixt.io.BeanReader;
import org.apache.commons.betwixt.io.BeanWriter;
/**
?????* 将javaBean 转成XML文件
?????*
?????* @param bean
?????* javaBean对象
?????* @return XML文件
?????*/
????public static File convertBean2XML(Object bean)
????{
????????File file = new File(FjhlUtils.generateFileName(Consts.XML_FILE_SUFFIX));
????????// FileWriter fw;
????????BeanWriter beanWriter = null;
????????OutputStreamWriter fw;
????????try
????????{
????????????fw = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
????????????beanWriter = new BeanWriter(fw);
????????????beanWriter.getXMLIntrospector().getConfiguration()
????????????????????.setAttributesForPrimitives(false);
????????????beanWriter.getBindingConfiguration().setMapIDs(false);
????????????beanWriter.setEndOfLine("\n");
????????????beanWriter.enablePrettyPrint();
????????????beanWriter.setWriteEmptyElements(true);
????????????beanWriter.setEndTagForEmptyElement(true);
????????????beanWriter.writeXmlDeclaration(Consts.XML_TITLE);
????????????beanWriter.write(bean);
????????????beanWriter.flush();
????????}
????????catch (IOException e)
????????{
????????????LOG.error("将javaBean 转成XML文件时发生IO异常", e);
????????}
????????catch (SAXException e)
????????{
????????????LOG.error("将javaBean 转成XML文件时发生SAX解析异常", e);
????????}
????????catch (IntrospectionException e)
????????{
????????????LOG.error("将javaBean 转成XML文件时发生内省异常", e);
????????}
????????finally
????????{
????????????try
????????????{
????????????????if (beanWriter != null)
????????????????{
????????????????????beanWriter.close();
????????????????????beanWriter = null;
????????????????}
????????????}
????????????catch (IOException e)
????????????{
????????????????LOG.error("转成XML文件时,关闭beanWriter失败",e);
????????????}
????????}
????????return file;
????}
??
??
?/**
?????* 将XML文件转成javaBean
?????*
?????* @param xmlFile
?????* XML文件
?????* @param clazz
?????* 生成javaBean Class对象
?????* @return Object javaBean对象
?????*/
????public static Object convertXML2Bean(File xmlFile, Class<?> clazz)
????{
????????Object bean = null;
????????BeanReader beanReader = new BeanReader();
????????beanReader.getXMLIntrospector().getConfiguration()
????????????????.setAttributesForPrimitives(false);
????????beanReader.getBindingConfiguration().setMapIDs(false);
????????try
????????{
????????????beanReader.registerBeanClass(clazz);
????????????bean = beanReader.parse(xmlFile);
????????}
????????catch (IntrospectionException e)
????????{
????????????LOG.error("将XML文件转成javaBean时发生内省异常", e);
????????}
????????catch (IOException e)
????????{
????????????LOG.error("将XML文件转成javaBean时发生IO异常", e);
????????}
????????catch (SAXException e)
????????{
????????????LOG.error("将XML文件转成javaBean时发生SAX解析异常", e);
????????}
????????return bean;
????}

将一组文件压缩成压缩文件

本文是用Java语言实现,使用的是java的类库。

实现的代码片段如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
/**
?????* 把一组文件压缩到指定的文件
?????*
?????* @param files
?????* 文件组
?????* @param zipFileName
?????* 要压缩成的文件名(包括路径)
?????* @param sPath
?????* ZIP中的路径
?????* @return 压缩文件
?????*/
????public static File compressFiles(File[] files,
String zipFileName,String sPath)
????{
????????String sUploadPath = "test";
????????File zipFile = new File(zipFileName);
????????FileOutputStream fout = null;
????????ZipOutputStream zipOut = null;
????????ZipInputStream zipIn = null;
????????FileInputStream fin = null;
????????byte[] buff = new byte[1024];
????????int rb;
????????try
????????{
????????????if (zipFile.exists())
????????????{
????????????????File fileBak =
?????????????????new File(zipFile.getAbsolutePath() + ".bak");
????????????????if (zipFile.renameTo(fileBak))
????????????????{
????????????????????logger.debug("重命名文件成功:" + fileBak.getName());
????????????????}
????????????????fin = new FileInputStream(fileBak);
????????????????zipIn = new ZipInputStream(fin);
????????????????fout = new FileOutputStream(zipFile);
????????????????zipOut = new ZipOutputStream(fout);
????????????????ZipEntry ze = null;
????????????????try
????????????????{
????????????????????while ((ze = zipIn.getNextEntry()) != null)
????????????????????{
????????????????????????zipOut.putNextEntry(ze);
????????????????????????while ((rb = zipIn.read(buff)) != -1)
????????????????????????{
????????????????????????????zipOut.write(buff, 0, rb);
????????????????????????}
????????????????????}
????????????????}
????????????????catch (Exception e)
????????????????{
????????????????????logger.error("aa", e);
????????????????}
????????????????finally
????????????????{
????????????????????safeCloseInputStream(fin);
????????????????????safeCloseInputStream(zipIn);
????????????????????safeDeleteFile(fileBak);
????????????????}
????????????}
????????????else
????????????{
????????????????fout = new FileOutputStream(zipFile);
????????????????zipOut = new ZipOutputStream(fout);
????????????}
????????????ZipEntry ze = null;
????????????for (int i = 0; i < files.length; i++)
????????????{
????????????????if (files[i] != null)
????????????????{
????????????????????try
????????????????????{
????????????????????????if (!files[i].exists())
????????????????????????{
????????????????????????????logger.error(
?????????????????????????????files[i].getAbsolutePath() + "不存在");
????????????????????????????continue;
????????????????????????}
????????????????????????fin = new FileInputStream(files[i]);
????????????????????????if (StringUtils.isBlank(sPath))
????????????????????????{
????????????????????????????ze = new ZipEntry(files[i].getName());
????????????????????????}
????????????????????????else
????????????????????????{
?????????????????????????StringBuffer sbZipEntry = new StringBuffer();
?????????????????????????sbZipEntry
?????????????????????????????.append(sPath)
?????????????????????????????.append(File.separator)
?????????????????????????????.append(files[i].getAbsolutePath()
?????????????????????????????.substring(sUploadPath.length()));
?????????????????????????ze = new ZipEntry(sbZipEntry.toString());
????????????????????????}
????????????????????????zipOut.putNextEntry(ze);
????????????????????????while ((rb = fin.read(buff)) != -1)
????????????????????????{
????????????????????????????zipOut.write(buff, 0, rb);
????????????????????????}
????????????????????}
????????????????????finally
????????????????????{
????????????????????????safeCloseInputStream(fin);
????????????????????}
????????????????}
????????????}
????????????logger.info("文件压缩成功:" + zipFile.getName());
????????????return zipFile;
????????}
????????catch (IOException e)
????????{
????????????logger.error(e);
????????????safeDeleteFile(zipFile);
????????????return null;
????????}
????????finally
????????{
????????????safeCloseOutStream(zipOut);
????????????safeCloseOutStream(fout);
????????}
????}