??xml version="1.0" encoding="utf-8" standalone="yes"?>
Eclipse插gQ?a >http://findbugs.sourceforge.net/downloads.html
插g理技?/strong>
提示Q新下蝲的插件PlugIn一定不要都攑֜原始的Eclipse目录下去?br />
使用
重新启动Eclipse后,在Help => About Eclipse SDK => Plug-in Details你可以看到由“FindBugs Project”提供的“FindBugs Plug-in”版?.0.17插gQ如下图所C:
FindBugs的用方?/strong>
FindBugs是一个可以在JavaE序中发现Bugs的程序?
它是专门用来L处于“Bug Patterns”列表中的代码的?
Bug Patterns指很有可能是错误的代码的实例?br />
目前FindBugs最高版?.9.4Q不q更新速度很快的,你应当经怸ȝ看是否有新版本发布。Eclipse plugin for FindBugs最高版?.0.17?br />
pȝ要求
使用FindBugs臛_需要JDK1.4.0以上版本QFindBugs是^台独立的Q可以运行于GNU/Linux、Windows、MacOS X {^C?br />
q行FindBugs臛_需要有256 MB内存Q如果你要分析一个很大的目Q那需要更加多的内存了?br />
FindBugs独立q行和与Antl合的详l操作就不介l了Q可以看官方的文?a target="_blank">http://findbugs.sourceforge.net/manual/
独立q行的效果图如下Q?br />
本文主要介绍在Eclipse中用的情况
打开Bug Details视图
Windows => Show View => Other?=> FindBugs => BugDetails
在Package Explorer或Navigator视图中,选中你的Java目Q右键,可以看到“Find Bugs”菜单项Q子菜单w有“Find Bugs”和“Clear Bug Markers”两内容,如下图所C:
我们建立一个简单的试文gTest.java 内容如下Q?
public class Test { private String[] name; public String[] getName() { return name; } public void setName(String[] name) { this.name = name; } }
我们点中“Find Bugs”,q行时会出现如下q度框:
q行l束后可以在Problems中看到增加了如下的警告信息内?br />
FindBugsq行后的警告信息内容不仅在Problems视图中显C,而且标记在源代码标记框中,在源代码~辑器中我们可以看到警告标识Q如下图Q?
当光标指向你的警告信息的代码上面Ӟ׃有相应的错误提示信息Q与Eclipse本n的错误或警告信息提示cM?
选中Problems视图里出现的相应问题Q就会在代码~辑器里切换到相应的代码上去Q方便根据相应的提示信息q行代码的修攏V?
在Problems视图里,选中相应的问题条目,右键Q在弹出的菜单中Q可以看到“Show Bug Details”,如下图所C:
点中它,会切换到Bug Details视图上去Q显C更加详l的提示信息?br />
当然Q在代码~辑H口中,点击带有警告提示信息的图标时Q也会自动切换到Bud DetailsH口去,查看详细的警告信息,如下图所C?br />
Ҏq里详细的信息,你可以得到FindBugsZ么会对你的代码报警告信息Q及相应的处理办法,Ҏ它的提示Q你可以快速方便地q行代码修改?br />
Ҏ提示Q我们将代码修改成如下,再运行就不会报有警告信息了?br />
public class Test { private String[] name; public String[] getName() { String[] temp = name; return temp; } public void setName(String[] name) { String[] temp = name; this.name = temp; } }
配置FindBugs
选择你的目Q右?=> Properties => FindBugs =>
可以配置的信息包括如上图所C的四个选项的相兌|:
ȝ
此插件的功能很不错,可以帮助我们提升Java代码的编写能力,写出更加安全可靠的代码。徏议用或加在Ant里进行持l构建?
现在Q你可以马上拿出你已l开发的一个项目,查一下你的代码有没有问题?/p>
在第二种模型中,我们可以清楚的把q?个类分ؓ三层Q?/p>
1、实体类层,即ItemQ带有domain logic的domain object
2、DAO层,即ItemDao和ItemDaoHibernateImplQ抽象持久化操作的接口和实现c?
3、业务逻辑层,即ItemManagerQ接受容器事务控Ӟ向Web层提供统一的服务调?/p>
在这三层中我们大家可以看刎ͼdomain object和DAO都是非常E_的层Q其实原因也很简单,因ؓdomain object是映数据库字段的,数据库字D不会频J变动,所以domain object也相对稳定,而面向数据库持久化编E的DAO层也不过是CRUD而已Q不会有更多的花P所以也很稳定?/p>
问题在于这个充当business workflow facade的业务逻辑对象Q它的变动是相当频繁的?span style="COLOR: red">业务逻辑对象通常都是无状态的、受事务控制的、Singletonc?/span>Q我们可以考察一下业务逻辑对象都有哪几cM务逻辑ҎQ?/p>
W一c:DAO接口Ҏ的代?/span>Q就是上面例子中的loadItemByIdҎ和findAllҎ?/p>
ItemManager之所以要代理q种c,目的有两个:向Web层提供统一的服务调用入口点和给持久化方法增加事务控制功?/span>。这两点都很Ҏ理解Q你不能既给Web层程序员提供xxxManagerQ也l他提供xxxDaoQ所以你需要用xxxManager装xxxDaoQ在q里Q充当了一个简单代理功能;而事务控制也是持久化Ҏ必须的,事务可能需要跨多个DAOҎ调用Q所以必L在业务逻辑层,而不能放在DAO层?/p>
但是必须看到Q对于一个典型的web应用来说Q绝大多数的业务逻辑都是单的CRUD逻辑Q所以这U情况下Q针Ҏ个DAOҎQxxxManager都需要提供一个对应的装ҎQ这不但是非常枯燥的Q也是o人感觉非怸好的?/p>
W二c:domain logic的方法代?/span>。就是上面例子中placeBidҎ。虽然Item已经有了placeBidҎQ但是ItemManager仍然需要封装一下Item的placeBidQ然后再提供一个简单封装之后的代理Ҏ?/p>
q和W一U情늱|其原因也一P也是ZlWeb层提供一个统一的服务调用入口点和给隐式的持久化动作提供事务控制?/p>
同样Q和W一U情况一P针对每个domain logicҎQxxxManager都需要提供一个对应的装ҎQ同h枯燥的,令h不爽的?/p>
W三c:需要多个domain object和DAO参与协作的business workflow。这U情冉|业务逻辑对象真正应该完成的职责?/p>
在这个简单的例子中,没有涉及到这U情况,不过大家都可以想像的出来q种应用场景Q因此不必D例说明了?/p>
通过上面的分析可以看出,只有W三cM务逻辑Ҏ才是业务逻辑对象真正应该承担的职责,而前两类业务逻辑Ҏ都是“无奈之䏀,不得不ؓ之的事情Q不但枯燥,而且令h沮?/p>
分析完了业务逻辑对象Q我们再回头看一下domain objectQ我们要仔细考察一下domain logic的话Q会发现domain logic也分Zc:
W一c:需要持久层框架隐式的实现透明持久化的domain logicQ例如Item的placeBidҎ中的q一句: 对于q一cdomain logicQ业务逻辑对象必须提供相应的封装方法,以实C务控制?/p> W二c:完全不依赖持久化的domain logicQ例如readonly例子中的TopicQ如下: 注意q个isAllowReplyҎQ他和持久化完全不发生一丁点关系。在实际的开发中Q我们同样会遇到很多q种不需要持久化的业务逻辑(主要发生在日期运、数D和枚Dq算斚w)Q这Udomain logic不管q不脱L在的框架Q它的行为都是一致的。对于这Udomain logicQ业务逻辑层ƈ不需要提供封装方法,它可以适用于Q何场合?/p>
this
.
getBids
().
add
(
newBid
);
上面已经着重提刎ͼ虽然q仅仅只是一个Java集合的添加新元素的操作,但是实际上通过事务的控Ӟ会潜在的触发两条SQLQ一条是insert一条记录到bid表,一条是更新item表相应的记录。如果我们让ItemqHibernateq行单元试Q它是一个单U的Java集合操作Q如果我们把他加入到Hibernate框架中,他就会潜在的触发两条SQLQ?span style="COLOR: red">q就是隐式的依赖于持久化的domain logic?
特别h意的一ҎQ在没有Hibernate/JDOq类可以实现“透明的持久化”工具出C前,q类domain logic是无法实现的?
class Topic{
booleanisAllowReply(){
CalendardueDate=Calendar.getInstance();
dueDate.setTime(lastUpdatedTime);
dueDate.add(Calendar.DATE,forum.timeToLive);
Datenow=newDate();
returnnow.after(dueDate.getTime());
}
}
W一U模型:只有getter/setterҎ的纯数据c,所有的业务逻辑完全由business object来完?又称TransactionScript)Q这U模型下的domain object被Martin FowlerUC为“血的domain object”。下面用举一个具体的代码来说明,代码来自Hibernate的caveatemptorQ但l过我的改写Q?/p>
一个实体类叫做ItemQ指的是一个拍卖项?
一个DAO接口cd做ItemDao
一个DAO接口实现cd做ItemDaoHibernateImpl
一个业务逻辑cd做ItemManager(或者叫做ItemService)
public class Item implements Serializable {
private Long id = null ;
private int version ;
private String name ;
private User seller ;
private String description ;
private MonetaryAmount initialPrice ;
private MonetaryAmount reservePrice ;
private Date startDate ;
private Date endDate ;
private Set categorizedItems = new HashSet ();
private Collection bids = new ArrayList ();
private Bid successfulBid ;
private ItemState state ;
private User approvedBy ;
private Date approvalDatetime ;
private Date created = new Date ();
/ / getter / setterҎ省略不写Q避免篇q太?/span>
}
public interface ItemDao {
public Item getItemById ( Long id );
public Collection findAll ();
public void updateItem ( Item item );
}
ItemDao定义持久化操作的接口Q用于隔L久化代码?/p>
public class ItemDaoHibernateImpl implements ItemDao extends HibernateDaoSupport {
public Item getItemById ( Long id ) {
return ( Item ) getHibernateTemplate (). load ( Item . class , id );
}
public Collection findAll () {
return ( List ) getHibernateTemplate (). find (" from Item ");
}
public void updateItem ( Item item ) {
getHibernateTemplate (). update ( item );
}
}
publicclass ItemManager{
privateItemDaoitemDao;
publicvoidsetItemDao(ItemDaoitemDao){this.itemDao=itemDao;}
publicBidloadItemById(Longid){
itemDao.loadItemById(id);
}
publicCollectionlistAllItems(){
returnitemDao.findAll();
}
publicBidplaceBid(Itemitem,Userbidder,MonetaryAmountbidAmount,
BidcurrentMaxBid,BidcurrentMinBid)throwsBusinessException{
if(currentMaxBid!=null&¤tMaxBid.getAmount().compareTo(bidAmount)>0){
thrownewBusinessException("Bid too low.");
}
//Auctionisactive
if(!state.equals(ItemState.ACTIVE))
thrownewBusinessException("Auction is not active yet.");
//Auctionstillvalid
if(item.getEndDate().before(newDate()))
thrownewBusinessException("Can't place new bid, auction already ended.");
//CreatenewBid
BidnewBid=newBid(bidAmount,item,bidder);
//PlacebidforthisItem
item.getBids().add(newBid);
itemDao.update(item);// 调用DAO完成持久化操?/span>
returnnewBid;
}
}
事务的管理是在ItemMangerq一层完成的QItemManager实现具体的业务逻辑。除了常见的和CRUD有关的简单逻辑之外Q这里还有一个placeBid的逻辑Q即目的竞标?/p>
以上是一个完整的W一U模型的CZ代码。在q个CZ中,placeBidQloadItemByIdQfindAll{等业务逻辑l统攑֜ItemManager中实玎ͼ而Item只有getter/setterҎ?br />
W二U模型,也就是Martin Fowler指的rich domain object是下面这样子的:
一个带有业务逻辑的实体类Q即domain object是Item
一个DAO接口ItemDao
一个DAO实现ItemDaoHibernateImpl
一个业务逻辑对象ItemManager
publicclass ItemimplementsSerializable{
// 所有的属性和getter/setterҎ同上Q省?/span>
publicBidplaceBid(Userbidder,MonetaryAmountbidAmount,
BidcurrentMaxBid,BidcurrentMinBid)
throwsBusinessException{
//Checkhighestbid(canalsobeadifferentStrategy(pattern))
if(currentMaxBid!=null&¤tMaxBid.getAmount().compareTo(bidAmount)>0){
thrownewBusinessException("Bid too low.");
}
//Auctionisactive
if(!state.equals(ItemState.ACTIVE))
thrownewBusinessException("Auction is not active yet.");
//Auctionstillvalid
if(this.getEndDate().before(newDate()))
thrownewBusinessException("Can't place new bid, auction already ended.");
//CreatenewBid
BidnewBid=newBid(bidAmount,this,bidder);
//PlacebidforthisItem
this.getBids.add(newBid);// h意这一句,透明的进行了持久化,但是不能在这里调?span class="constant">ItemDaoQItem不能对ItemDao产生依赖Q?/span>
returnnewBid;
}
}
竞标q个业务逻辑被放入到Item中来。请注意this.getBids.add(newBid); 如果没有Hibernate或者JDOq种O/R Mapping的支持,我们是无法实现这U透明的持久化行ؓ的。但是请注意QItem里面不能去调用ItemDAOQ对ItemDAO产生依赖Q?/p>
ItemDao和ItemDaoHibernateImpl的代码同上,省略?/p>
publicclass ItemManager{
privateItemDaoitemDao;
publicvoidsetItemDao(ItemDaoitemDao){this.itemDao=itemDao;}
publicBidloadItemById(Longid){
itemDao.loadItemById(id);
}
publicCollectionlistAllItems(){
returnitemDao.findAll();
}
publicBidplaceBid(Itemitem,Userbidder,MonetaryAmountbidAmount,
BidcurrentMaxBid,BidcurrentMinBid)throwsBusinessException{
item.placeBid(bidder,bidAmount,currentMaxBid,currentMinBid);
itemDao.update(item);// 必须昑ּ的调?span class="constant">DAOQ保持持久化
}
}
在第二种模型中,placeBid业务逻辑是放在Item中实现的Q而loadItemById和findAll业务逻辑是放在ItemManager中实现的。不q值得注意的是Q即使placeBid业务逻辑攑֜Item中,你仍焉要在ItemManager中简单的装一层,以保证对placeBid业务逻辑q行事务的管理和持久化的触发?/p>
q种模型是Martin Fowler所指的真正的domain model。在q种模型中,有三个业务逻辑ҎQplaceBidQloadItemById和findAllQ现在的问题是哪个逻辑应该攑֜Item中,哪个逻辑应该攑֜ItemManager中。在我们q个例子中,placeBid攑֜Item?但是ItemManager也需要对它进行简单的装)QloadItemById和findAll是放在ItemManager中的?/p>
切分的原则是什么呢Q?Rod Johnson提出原则是“case by case”,可重用度高的Q和domain object状态密切关联的攑֜Item中,可重用度低的Q和domain object状态没有密切关联的攑֜ItemManager中?/p>
我提出的原则是:看业务方法是否显式的依赖持久化?/span>
Item的placeBidq个业务逻辑Ҏ没有昑ּ的对持久化ItemDao接口产生依赖Q所以要攑֜Item中?span style="COLOR: red">h意,如果q了Hibernateq个持久化框ӞItemq个domain object是可以进行单元测试的Q他不依赖于Hibernate的持久化机制。它是一个独立的Q可UL的,完整的,自包含的域对?/span>?/p>
而loadItemById和findAllq两个业务逻辑Ҏ是必L式的Ҏ久化ItemDao接口产生依赖Q否则这个业务逻辑无法完成。如果你要把q两个方法放在Item中,那么Item无法脱Hibernate框架Q无法在Hibernate框架之外独立存在?br />
W三U模型印象中好像是firebody或者是Archie提出?也有可能不是Q记不清楚了)Q简单的来说Q这U模型就是把W二U模型的domain object和business object合二Z了。所以ItemManager׃需要了Q在q种模型下面Q只有三个类Q他们分别是Q?/p>
ItemQ包含了实体cM息,也包含了所有的业务逻辑
ItemDaoQ持久化DAO接口c?
ItemDaoHibernateImplQDAO接口的实现类
׃ItemDao和ItemDaoHibernateImpl和上面完全相同,q略了?/p>
publicclass ItemimplementsSerializable{
// 所有的属性和getter/setterҎ都省?/span>
privatestaticItemDaoitemDao;
publicvoidsetItemDao(ItemDaoitemDao){this.itemDao=itemDao;}
publicstaticItemloadItemById(Longid){
return(Item)itemDao.loadItemById(id);
}
publicstaticCollectionfindAll(){
return(List)itemDao.findAll();
}publicBidplaceBid(Userbidder,MonetaryAmountbidAmount,
BidcurrentMaxBid,BidcurrentMinBid)
throwsBusinessException{
//Checkhighestbid(canalsobeadifferentStrategy(pattern))
if(currentMaxBid!=null&¤tMaxBid.getAmount().compareTo(bidAmount)>0){
thrownewBusinessException("Bid too low.");
}
//Auctionisactive
if(!state.equals(ItemState.ACTIVE))
thrownewBusinessException("Auction is not active yet.");
//Auctionstillvalid
if(this.getEndDate().before(newDate()))
thrownewBusinessException("Can't place new bid, auction already ended.");
//CreatenewBid
BidnewBid=newBid(bidAmount,this,bidder);
//PlacebidforthisItem
this.addBid(newBid);
itemDao.update(this);// 调用DAOq行昑ּ持久?/span>
returnnewBid;
}
}
在这U模型中Q所有的业务逻辑全部都在Item中,事务理也在Item中实现?/p>
(转蝲Q?/p>
html在线~辑器对于我们作新闻产品之类的程序是很重要的Q在|上扑ֽ了好了好一D|_发现FCKeditor,跨^台的Q正在进行的jsp目正需要这ƾhtml在线~辑器。试用了一下FCKeditor,Ҏ|上的文章小l一下:
1.下蝲
FCKeditor.java 2.3 (FCKeditot for java)
FCKeditor 2.2 (FCKeditor基本文g)
以下是下载地址Q?br />http://www.fckeditor.net/download/default.html
2.建立目:
建立目tomcat/webapps/TestFCKeditor.
3.FCKeditor2.2解压~?/b>
FCKeditor2.2解压~?整个目录FCKeditor复制到项目的根目录下Q?br />目录l构为:tomcat/webapps/TestFCKeditor/FCKeditor
然后FCKeditor-2.3.zipQjavaQ压~包中\web\WEB-INF\lib\目录下的两个jar文g拷到目的\WEB-INF\lib\目录下。把其中的src目录下的FCKeditor.tld文gcopy到TestFCKedit/FCKeitor/WEB-INF/?br />
4.合ƈweb.xml:
FCKeditor-2.3.zip压羃包中\web\WEB-INF\目录下的web.xml文g合ƈ到项目的\WEB-INF\目录下的web.xml文g中?br />
5. 修改合ƈ后的web.xml文g
修改合ƈ后的web.xml文gQ将名ؓSimpleUploader的Servlet的enabled参数值改为trueQ?br />以允怸传功能,Connector Servlet的baseDir参数值用于设|上传文件存攄位置?br />d标签定义:
<taglib>
<taglib-uri>/TestFCKeditor</taglib-uri>
<taglib-location>/WEB-INF/FCKeditor.tld</taglib-location>
</taglib>
q行图:
license name: csdn license key: pLR8ZC-956-55-5467865159452715
hello uLR8ZC-955-56-6067865798739181
License Name : shangxingxian
License Key : fLR8ZC-955-56-6067865930680921
=============4.1
basten
oLR8ZC|957444|535353|6546801608
pass:uLR8ZC-956-55-5467865991428004
user:hehe
希望能够帮助那些正在L注册码的朋友!